Completed
Push — master ( 708c0e...18f94d )
by Alexandr
28:28 queued 14:38
created

ResolveValidator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * Date: 03.11.16
4
 *
5
 * @author Portey Vasil <[email protected]>
6
 */
7
8
namespace Youshido\GraphQL\Validator\ResolveValidator;
9
10
11
use Youshido\GraphQL\Exception\ResolveException;
12
use Youshido\GraphQL\Execution\Context\ExecutionContext;
13
use Youshido\GraphQL\Execution\Request;
14
use Youshido\GraphQL\Field\FieldInterface;
15
use Youshido\GraphQL\Field\InputField;
16
use Youshido\GraphQL\Parser\Ast\Interfaces\FieldInterface as AstFieldInterface;
17
use Youshido\GraphQL\Type\AbstractType;
18
use Youshido\GraphQL\Type\InterfaceType\AbstractInterfaceType;
19
use Youshido\GraphQL\Type\Object\AbstractObjectType;
20
use Youshido\GraphQL\Type\TypeMap;
21
use Youshido\GraphQL\Type\TypeService;
22
use Youshido\GraphQL\Type\Union\AbstractUnionType;
23
24
class ResolveValidator implements ResolveValidatorInterface
25 68
{
26
27
    /** @var ExecutionContext */
28 68
    private $executionContext;
29
30 3
31 3
    /**
32 3
     * ResolveValidator constructor.
33
     *
34 68
     * @param ExecutionContext $executionContext
35
     */
36
    public function __construct(ExecutionContext $executionContext)
37
    {
38 67
        $this->executionContext = $executionContext;
39 50
    }
40 67
    
41
    public function assetTypeHasField(AbstractType $objectType, AstFieldInterface $ast)
42 67
    {
43 37
        /** @var AbstractObjectType $objectType */
44 1
        if ($this->executionContext->getField($objectType, $ast->getName()) !== null) {
45
            return;
46
        }
47 37
        
48 37
        if (!(TypeService::isObjectType($objectType) || TypeService::isInputObjectType($objectType)) || !$objectType->hasField($ast->getName())) {
49
            $availableFieldNames = implode(', ', array_map(function (FieldInterface $field) {
50 37
                return sprintf('"%s"', $field->getName());
51 37
            }, $objectType->getFields()));
52 35
            throw new ResolveException(sprintf('Field "%s" not found in type "%s". Available fields are: %s', $ast->getName(), $objectType->getNamedType()->getName(), $availableFieldNames), $ast->getLocation());
53 16
        }
54 11
    }
55 37
56 6
    public function assertValidArguments(FieldInterface $field, AstFieldInterface $query, Request $request)
57 6
    {
58
        $requiredArguments = array_filter($field->getArguments(), function (InputField $argument) {
59
            return $argument->getType()->getKind() === TypeMap::KIND_NON_NULL;
60 34
        });
61
62
        foreach ($query->getArguments() as $astArgument) {
63
            if (!$field->hasArgument($astArgument->getName())) {
64
                throw new ResolveException(sprintf('Unknown argument "%s" on field "%s"', $astArgument->getName(), $field->getName()), $astArgument->getLocation());
65
            }
66 34
67 34
            $argument     = $field->getArgument($astArgument->getName());
68
            $argumentType = $argument->getType()->getNullableType();
69
70
            switch ($argumentType->getKind()) {
71 64
                case TypeMap::KIND_ENUM:
72 3
                case TypeMap::KIND_SCALAR:
73
                case TypeMap::KIND_INPUT_OBJECT:
74 62
                case TypeMap::KIND_LIST:
75
                    if (!$argument->getType()->isValidValue($astArgument->getValue())) {
76 62
                        $error = $argument->getType()->getValidationError($astArgument->getValue()) ?: '(no details available)';
77
                        throw new ResolveException(sprintf('Not valid type for argument "%s" in query "%s": %s', $astArgument->getName(), $field->getName(), $error), $astArgument->getLocation());
78 62
                    }
79 4
80
                    break;
81
82 60
                default:
83 60
                    throw new ResolveException(sprintf('Invalid argument type "%s"', $argumentType->getName()));
84 3
            }
85 3
86 3
            if (array_key_exists($astArgument->getName(), $requiredArguments) || $argument->getConfig()->get('defaultValue') !== null) {
87
                unset($requiredArguments[$astArgument->getName()]);
88 59
            }
89
        }
90 6
91
        if (count($requiredArguments)) {
92 6
            throw new ResolveException(sprintf('Require "%s" arguments to query "%s"', implode(', ', array_keys($requiredArguments)), $query->getName()));
93 6
        }
94 6
    }
95 6
96
    public function assertValidResolvedValueForField(FieldInterface $field, $resolvedValue)
97
    {
98
        if (null === $resolvedValue && $field->getType()->getKind() === TypeMap::KIND_NON_NULL) {
99
            throw new ResolveException(sprintf('Cannot return null for non-nullable field "%s"', $field->getName()));
100
        }
101
102
        $nullableFieldType = $field->getType()->getNullableType();
103 2
        if (!$nullableFieldType->isValidValue($resolvedValue)) {
104
            $error = $nullableFieldType->getValidationError($resolvedValue) ?: '(no details available)';
105 2
            throw new ResolveException(sprintf('Not valid resolved type for field "%s": %s', $field->getName(),
106 2
                $error));
107 2
        }
108
    }
109
110
    public function assertTypeImplementsInterface(AbstractType $type, AbstractInterfaceType $interface)
111 1
    {
112
        if ($type instanceof AbstractObjectType) {
113
            foreach ($type->getInterfaces() as $typeInterface) {
114
                if ($typeInterface->getName() === $interface->getName()) {
115
                    return;
116
                }
117
            }
118
        }
119
120
        throw new ResolveException(sprintf('Type "%s" does not implement "%s"', $type->getName(), $interface->getName()));
121
    }
122
123
    public function assertTypeInUnionTypes(AbstractType $type, AbstractUnionType $unionType)
124
    {
125
        foreach ($unionType->getTypes() as $unionTypeItem) {
126
            if ($unionTypeItem->getName() === $type->getName()) {
127
                return;
128
            }
129
        }
130
131
        throw new ResolveException(sprintf('Type "%s" not exist in types of "%s"', $type->getName(), $unionType->getName()));
132
    }
133
}
134