Completed
Push — master ( d477df...2ebd55 )
by Portey
26:14 queued 26:14
created

Processor::getResolveValidator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
/*
3
* This file is a part of graphql-youshido project.
4
*
5
* @author Portey Vasil <[email protected]>
6
* @author Alexandr Viniychuk <[email protected]>
7
* created: 11/28/15 1:05 AM
8
*/
9
10
namespace Youshido\GraphQL;
11
12
use Symfony\Component\PropertyAccess\PropertyAccess;
13
use Symfony\Component\PropertyAccess\PropertyAccessor;
14
use Youshido\GraphQL\Introspection\SchemaType;
15
use Youshido\GraphQL\Introspection\TypeDefinitionType;
16
use Youshido\GraphQL\Parser\Ast\FragmentReference;
17
use Youshido\GraphQL\Parser\Ast\Mutation;
18
use Youshido\GraphQL\Parser\Ast\Query;
19
use Youshido\GraphQL\Parser\Ast\TypedFragmentReference;
20
use Youshido\GraphQL\Parser\Parser;
21
use Youshido\GraphQL\Type\Field\Field;
22
use Youshido\GraphQL\Type\Object\AbstractEnumType;
23
use Youshido\GraphQL\Type\Object\InputObjectType;
24
use Youshido\GraphQL\Type\Object\ObjectType;
25
use Youshido\GraphQL\Type\Scalar\AbstractScalarType;
26
use Youshido\GraphQL\Type\TypeInterface;
27
use Youshido\GraphQL\Type\TypeMap;
28
use Youshido\GraphQL\Validator\Exception\ResolveException;
29
use Youshido\GraphQL\Validator\ResolveValidator\ResolveValidatorInterface;
30
31
class Processor
32
{
33
34
    const TYPE_NAME_QUERY = '__typename';
35
36
    /** @var  array */
37
    protected $data;
38
39
    /** @var ResolveValidatorInterface */
40
    protected $resolveValidator;
41
42
    /** @var Schema */
43
    protected $schema;
44
45
    /** @var PropertyAccessor */
46
    protected $propertyAccessor;
47
48
    /** @var Request */
49
    protected $request;
50
51 18
    public function __construct(ResolveValidatorInterface $validator)
52
    {
53 18
        $this->resolveValidator = $validator;
54
55 18
        $this->propertyAccessor = PropertyAccess::createPropertyAccessor();
56 18
    }
57
58 18
    public function processQuery($queryString, $variables = [])
59
    {
60 18
        $this->resolveValidator->clearErrors();
61 18
        $this->data = [];
62
63
        try {
64 18
            $this->parseAndCreateRequest($queryString, $variables);
65
66 18
            if ($this->request->hasQueries()) {
67 18
                foreach ($this->request->getQueries() as $query) {
68 18
                    if ($queryResult = $this->executeQuery($query, $this->getSchema()->getQueryType())) {
69 17
                        $this->data = array_merge($this->data, $queryResult);
70 17
                    };
71 18
                }
72 18
            }
73
74 18
            if ($this->request->hasMutations()) {
75
                foreach ($this->request->getMutations() as $mutation) {
76
                    if ($mutationResult = $this->executeMutation($mutation, $this->getSchema()->getMutationType())) {
77
                        $this->data = array_merge($this->data, $mutationResult);
78
                    }
79
                }
80
            }
81 18
        } catch (\Exception $e) {
82
            $this->resolveValidator->clearErrors();
83
84
            $this->resolveValidator->addError($e);
85
        }
86 18
    }
87
88
    /**
89
     * @param Mutation        $mutation
90
     * @param InputObjectType $objectType
91
     *
92
     * @return array|bool|mixed
93
     */
94 1
    protected function executeMutation($mutation, $objectType)
95
    {
96
        if (!$this->checkFieldExist($objectType, $mutation)) {
97
98
            return null;
99
        }
100
101
        /** @var Field $field */
102
        $field = $objectType->getConfig()->getField($mutation->getName());
103
104
        if (!$this->resolveValidator->validateArguments($field, $mutation, $this->request)) {
105
            return null;
106
        }
107
108
        $alias         = $mutation->hasAlias() ? $mutation->getAlias() : $mutation->getName();
109
        $resolvedValue = $this->resolveValue($field, null, $mutation);
110
111
        if (!$this->resolveValidator->validateResolvedValue($resolvedValue, $field->getType()->getKind())) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
112
            $this->resolveValidator->addError(new ResolveException(sprintf('Not valid resolved value for mutation "%s"', $field->getType()->getName())));
113
114
            return [$alias => null];
115
        }
116
117
        $value = null;
118
        if ($mutation->hasFields()) {
119
            $outputType = $field->getType()->getOutputType();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Youshido\GraphQL\Type\TypeInterface as the method getOutputType() does only exist in the following implementations of said interface: Youshido\GraphQL\Type\Object\AbstractMutationType.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
120
121
            if ($outputType && in_array($outputType->getKind(), [TypeMap::KIND_INTERFACE, TypeMap::KIND_UNION])) {
122
                $outputType = $outputType->getConfig()->resolveType($resolvedValue);
123
            }
124
125
            if ($outputType->getKind() == TypeMap::KIND_LIST) {
126
                foreach ($resolvedValue as $resolvedValueItem) {
127
                    $value[] = [];
128
                    $index   = count($value) - 1;
129
130 View Code Duplication
                    if (in_array($outputType->getConfig()->getItem()->getKind(), [TypeMap::KIND_UNION, TypeMap::KIND_INTERFACE])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
131
                        $type = $outputType->getConfig()->getItemConfig()->resolveType($resolvedValueItem);
132
                    } else {
133
                        $type = $outputType;
134
                    }
135
136 1
                    $value[$index] = $this->processQueryFields($mutation, $type, $resolvedValueItem, $value[$index]);
137
                }
138
            } else {
139
                $value = $this->processQueryFields($mutation, $outputType, $resolvedValue, []);
140
            }
141
        }
142
143
        return [$alias => $value];
144
    }
145
146 18
    protected function parseAndCreateRequest($query, $variables = [])
147
    {
148 18
        $parser = new Parser();
149
150 18
        $parser->setSource($query);
151 18
        $data = $parser->parse();
152
153 18
        $this->request = new Request($data);
154 18
        $this->request->setVariables($variables);
155 18
    }
156
157
    /**
158
     * @param Query|Field $query
159
     * @param ObjectType  $currentLevelSchema
160
     * @param null        $contextValue
161
     * @return array|bool|mixed
162
     */
163 18
    protected function executeQuery($query, $currentLevelSchema, $contextValue = null)
164
    {
165 18
        if (!$this->checkFieldExist($currentLevelSchema, $query)) {
166
            return null;
167
        }
168
169
        /** @var Field $field */
170 18
        $field = $currentLevelSchema->getConfig()->getField($query->getName());
171 18
        if (get_class($query) == 'Youshido\GraphQL\Parser\Ast\Field') {
172 16
            $alias            = $query->getAlias() ?: $query->getName();
173 16
            $preResolvedValue = $this->getPreResolvedValue($contextValue, $query);
174
175 16
            if ($field->getConfig()->getType()->getKind() == TypeMap::KIND_LIST) {
176 1
                if (!is_array($preResolvedValue)) {
177
                    $value = null;
0 ignored issues
show
Unused Code introduced by
$value is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
178
                    $this->resolveValidator->addError(new ResolveException('Not valid resolve value for list type'));
179
                }
180
181
182 1
                $listValue = [];
183 1
                foreach ($preResolvedValue as $resolvedValueItem) {
0 ignored issues
show
Bug introduced by
The expression $preResolvedValue of type object|integer|double|string|null|boolean|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
184
                    /** @var TypeInterface $type */
185 1
                    $type = $field->getType()->getConfig()->getItem();
186
187 1
                    if ($type->getKind() == TypeMap::KIND_ENUM) {
188
                        /** @var $type AbstractEnumType */
189 1
                        if (!$type->isValidValue($resolvedValueItem)) {
190
                            $this->resolveValidator->addError(new ResolveException('Not valid value for enum type'));
191
192
                            $listValue = null;
193
                            break;
194
                        }
195
196 1
                        $listValue[] = $type->resolve($resolvedValueItem);
197 1
                    } else {
198
                        /** @var AbstractScalarType $type */
199
                        $listValue[] = $type->serialize($preResolvedValue);
200
                    }
201 1
                }
202
203 1
                $value = $listValue;
204 1
            } else {
205 16 View Code Duplication
                if ($field->getType()->getKind() == TypeMap::KIND_ENUM) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
206
                    if (!$field->getType()->isValidValue($preResolvedValue)) {
207
                        $this->resolveValidator->addError(new ResolveException('Not valid value for enum type'));
208
                        $value = null;
209
                    } else {
210
                        $value = $field->getType()->resolve($preResolvedValue);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Youshido\GraphQL\Type\TypeInterface as the method resolve() does only exist in the following implementations of said interface: Youshido\GraphQL\Introspection\DirectiveListType, Youshido\GraphQL\Introspection\DirectiveType, Youshido\GraphQL\Introspection\EnumValueListType, Youshido\GraphQL\Introspection\EnumValueType, Youshido\GraphQL\Introspection\FieldListType, Youshido\GraphQL\Introspection\FieldType, Youshido\GraphQL\Introspection\InputValueListType, Youshido\GraphQL\Introspection\InputValueType, Youshido\GraphQL\Introspection\InterfaceListType, Youshido\GraphQL\Introspection\MutationType, Youshido\GraphQL\Introspection\QueryListType, Youshido\GraphQL\Introspection\QueryType, Youshido\GraphQL\Introspection\SchemaType, Youshido\GraphQL\Introspection\TypeDefinitionType, Youshido\GraphQL\Type\ListType\AbstractListType, Youshido\GraphQL\Type\ListType\ListType, Youshido\GraphQL\Type\Object\AbstractEnumType, Youshido\GraphQL\Type\Ob...AbstractInputObjectType, Youshido\GraphQL\Type\Object\AbstractMutationType, Youshido\GraphQL\Type\Object\AbstractObjectType, Youshido\GraphQL\Type\Object\AbstractUnionType, Youshido\GraphQL\Type\Object\EnumType, Youshido\GraphQL\Type\Object\InputObjectType, Youshido\GraphQL\Type\Object\ObjectType, Youshido\Tests\DataProvider\UserType, Youshido\Tests\StarWars\Schema\DroidType, Youshido\Tests\StarWars\Schema\EpisodeEnum, Youshido\Tests\StarWars\Schema\HumanType, Youshido\Tests\StarWars\Schema\QueryType, Youshido\Tests\Type\Union\Schema\FirstType, Youshido\Tests\Type\Union\Schema\QueryType, Youshido\Tests\Type\Union\Schema\SecondType, Youshido\Tests\Type\Union\Schema\TestUnionType.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
211
                    }
212
                } else {
213 16
                    $value = $field->getType()->serialize($preResolvedValue);
214
                }
215
            }
216 16
        } else {
217 18
            if (!$this->resolveValidator->validateArguments($field, $query, $this->request)) {
218 1
                return null;
219
            }
220
221 17
            $resolvedValue = $this->resolveValue($field, $contextValue, $query);
222 17
            $alias         = $query->hasAlias() ? $query->getAlias() : $query->getName();
0 ignored issues
show
Bug introduced by
The method hasAlias does only exist in Youshido\GraphQL\Parser\Ast\Query, but not in Youshido\GraphQL\Type\Field\Field.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
Bug introduced by
The method getAlias does only exist in Youshido\GraphQL\Parser\Ast\Query, but not in Youshido\GraphQL\Type\Field\Field.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
223
224 17
            if (!$this->resolveValidator->validateResolvedValue($resolvedValue, $field->getType()->getKind())) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
225
                $this->resolveValidator->addError(new ResolveException(sprintf('Not valid resolved value for query "%s"', $field->getType()->getName())));
226
227
                return [$alias => null];
228
            }
229
230 17
            $value = [];
231 17
            if ($resolvedValue) {
232 16
                if ($field->getType()->getKind() == TypeMap::KIND_LIST) {
233 7
                    foreach ($resolvedValue as $resolvedValueItem) {
234 7
                        $value[] = [];
235 7
                        $index   = count($value) - 1;
236
237 7
                        if (in_array($field->getConfig()->getType()->getConfig()->getItem()->getKind(), [TypeMap::KIND_UNION, TypeMap::KIND_INTERFACE])) {
238 4
                            $type = $field->getConfig()->getType()->getConfig()->getItemConfig()->resolveType($resolvedValueItem);
239 4
                        } else {
240 3
                            $type = $field->getType();
241
                        }
242
243 7
                        $value[$index] = $this->processQueryFields($query, $type, $resolvedValueItem, $value[$index]);
244 7
                    }
245 7
                } else {
246 14
                    $value = $this->processQueryFields($query, $field->getType(), $resolvedValue, $value);
247
                }
248 16
            } else {
249 4
                $value = $resolvedValue;
250
            }
251
        }
252
253 17
        return [$alias => $value];
254
    }
255
256
    /**
257
     * @param $objectType InputObjectType|ObjectType
258
     * @param $query      Mutation|Query
259
     * @return null
260
     */
261 18
    private function checkFieldExist($objectType, $query)
262
    {
263 18 View Code Duplication
        if (!$objectType->getConfig()->hasField($query->getName())) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
264
            if ($objectType->getKind() == TypeMap::KIND_LIST) {
265
                $name = $objectType->getConfig()->getItem()->getName();
266
            } else {
267
                $name = $objectType->getName();
268
            }
269
270
            $this->resolveValidator->addError(new ResolveException(sprintf('Field "%s" not found in type "%s"', $query->getName(), $name)));
271
272
            return false;
273
        }
274
275 18
        return true;
276
    }
277
278
    /**
279
     * @param $value
280
     * @param $query Field
281
     *
282
     * @throws \Exception
283
     *
284
     * @return mixed
285
     */
286 16
    protected function getPreResolvedValue($value, $query)
287
    {
288 16
        if (is_array($value)) {
289 11
            if (array_key_exists($query->getName(), $value)) {
290 11
                return $value[$query->getName()];
291
            } else {
292
                throw new \Exception('Not found in resolve result', $query->getName());
293
            }
294 5
        } elseif (is_object($value)) {
295 5
            return $this->propertyAccessor->getValue($value, $query->getName());
296
        }
297
298
        return $value;
299
    }
300
301
    /**
302
     * @param $field        Field
303
     * @param $contextValue mixed
304
     * @param $query        Query
305
     *
306
     * @return mixed
307
     */
308 17
    protected function resolveValue($field, $contextValue, $query)
309
    {
310 17
        $resolvedValue = $field->getConfig()->resolve($contextValue, $this->parseArgumentsValues($field, $query));
311
312 17 View Code Duplication
        if (in_array($field->getType()->getKind(), [TypeMap::KIND_UNION, TypeMap::KIND_INTERFACE])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
313 6
            $resolvedType = $field->getType()->resolveType($resolvedValue);
314 6
            $field->setType($resolvedType);
315 6
        }
316
317 17
        return $resolvedValue;
318
    }
319
320
    /**
321
     * @param $field     Field
322
     * @param $query     Query
323
     *
324
     * @return array
325
     */
326 17
    public function parseArgumentsValues($field, $query)
327
    {
328 17
        if ($query instanceof \Youshido\GraphQL\Parser\Ast\Field) {
329
            return [];
330
        }
331
332 17
        $args = [];
333 17
        foreach ($query->getArguments() as $argument) {
334 5
            $args[$argument->getName()] = $field->getConfig()->getArgument($argument->getName())->getType()->parseValue($argument->getValue()->getValue());
335 17
        }
336
337 17
        return $args;
338
    }
339
340
    /**
341
     * @param $query         Query
342
     * @param $queryType     ObjectType|TypeInterface|Field
343
     * @param $resolvedValue mixed
344
     * @param $value         array
345
     *
346
     * @throws \Exception
347
     *
348
     * @return array
349
     */
350 16
    protected function processQueryFields($query, $queryType, $resolvedValue, $value)
351
    {
352 16
        foreach ($query->getFields() as $field) {
353 16
            if ($field instanceof FragmentReference) {
354 1
                if (!$fragment = $this->request->getFragment($field->getName())) {
355
                    throw new \Exception(sprintf('Fragment reference "%s" not found', $field->getName()));
356
                }
357
358 1
                if ($fragment->getModel() !== $queryType->getName()) {
359
                    throw new \Exception(sprintf('Fragment reference "%s" not found on model "%s"', $field->getName(), $queryType->getName()));
360
                }
361
362 1
                foreach ($fragment->getFields() as $fragmentField) {
363 1
                    $value = $this->collectValue($value, $this->executeQuery($fragmentField, $queryType, $resolvedValue));
364 1
                }
365 16
            } elseif ($field instanceof TypedFragmentReference) {
366 2
                if ($field->getTypeName() !== $queryType->getName()) {
367 1
                    continue;
368
                }
369
370 2
                foreach ($field->getFields() as $fragmentField) {
371 2
                    $value = $this->collectValue($value, $this->executeQuery($fragmentField, $queryType, $resolvedValue));
0 ignored issues
show
Documentation introduced by
$fragmentField is of type object<Youshido\GraphQL\Parser\Ast\Field>, but the function expects a object<Youshido\GraphQL\...aphQL\Type\Field\Field>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
372 2
                }
373 16
            } elseif ($field->getName() == self::TYPE_NAME_QUERY) {
374 1
                $value = $this->collectValue($value, [$field->getAlias() ?: $field->getName() => $queryType->getName()]);
375 1
            } else {
376 16
                $value = $this->collectValue($value, $this->executeQuery($field, $queryType, $resolvedValue));
377
            }
378 16
        }
379
380 16
        return $value;
381
    }
382
383 16
    protected function collectValue($value, $queryValue)
384
    {
385 16
        if ($queryValue && is_array($queryValue)) {
386 16
            $value = array_merge(is_array($value) ? $value : [], $queryValue);
387 16
        } else {
388
            $value = $queryValue;
389
        }
390
391 16
        return $value;
392
    }
393
394 18
    public function getSchema()
395
    {
396 18
        return $this->schema;
397
    }
398
399 18
    public function setSchema(Schema $schema)
400
    {
401 18
        $this->schema = $schema;
402
403 18
        $__schema = new SchemaType();
404 18
        $__schema->setSchema($schema);
405
406 18
        $__type = new TypeDefinitionType();
407
408 18
        $this->schema->addQuery('__schema', $__schema);
409 18
        $this->schema->addQuery('__type', $__type);
410 18
    }
411
412
    /**
413
     * @return ResolveValidatorInterface
414
     */
415
    public function getResolveValidator()
416
    {
417
        return $this->resolveValidator;
418
    }
419
420 18
    public function getResponseData()
421
    {
422 18
        $result = [];
423
424 18
        if (!empty($this->data)) {
425 17
            $result['data'] = $this->data;
426 17
        }
427
428 18
        if ($this->resolveValidator->hasErrors()) {
429 1
            $result['errors'] = $this->resolveValidator->getErrorsArray();
430 1
        }
431
432 18
        return $result;
433
    }
434
}
435