Completed
Pull Request — master (#159)
by Christoffer
02:45
created

RootTypesRule::validateRootType()   C

Complexity

Conditions 8
Paths 3

Size

Total Lines 30
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 18
nc 3
nop 2
1
<?php
2
3
namespace Digia\GraphQL\SchemaValidation\Rule;
4
5
use Digia\GraphQL\Error\SchemaValidationException;
6
use Digia\GraphQL\Language\Node\NodeInterface;
7
use Digia\GraphQL\Language\Node\OperationTypeDefinitionNode;
8
use Digia\GraphQL\Language\Node\SchemaDefinitionNode;
9
use Digia\GraphQL\SchemaValidation\ValidationContext;
10
use Digia\GraphQL\Type\Definition\ObjectType;
11
use Digia\GraphQL\Type\Definition\TypeInterface;
12
use Digia\GraphQL\Type\SchemaInterface;
13
use function Digia\GraphQL\Util\find;
14
15
class RootTypesRule extends AbstractRule
16
{
17
    /**
18
     * @inheritdoc
19
     */
20
    public function evaluate(): void
21
    {
22
        $schema = $this->context->getSchema();
23
24
        $rootTypes = [
25
            'query'        => $schema->getQueryType(),
26
            'mutation'     => $schema->getMutationType(),
27
            'subscription' => $schema->getSubscriptionType(),
28
        ];
29
30
        foreach ($rootTypes as $operation => $rootType) {
31
            $this->validateRootType($rootType, $operation);
32
        }
33
    }
34
35
    /**
36
     * @param TypeInterface|null $rootType
37
     * @param string             $operation
38
     */
39
    protected function validateRootType(?TypeInterface $rootType, string $operation): void
40
    {
41
        $schema = $this->context->getSchema();
42
43
        if ($operation === 'query' && null === $rootType) {
44
            $this->context->reportError(
45
                new SchemaValidationException(
46
                    \sprintf('%s root type must be provided.', \ucfirst($operation)),
47
                    $schema->hasAstNode() ? [$schema->getAstNode()] : null
48
                )
49
            );
50
51
            return;
52
        }
53
54
        if (null !== $rootType && !($rootType instanceof ObjectType)) {
55
            $this->context->reportError(
56
                new SchemaValidationException(
57
                    \sprintf(
58
                        $operation === 'query'
59
                            ? '%s root type must be Object type, it cannot be %s.'
60
                            : '%s root type must be Object type if provided, it cannot be %s.',
61
                        \ucfirst($operation),
62
                        (string)$rootType
63
                    ),
64
                    null !== $rootType ? [$this->getOperationTypeNode($schema, $rootType, $operation)] : null
65
                )
66
            );
67
68
            return;
69
        }
70
    }
71
72
    /**
73
     * @param SchemaInterface          $schema
74
     * @param TypeInterface|ObjectType $type
75
     * @param string                   $operation
76
     * @return NodeInterface|null
77
     */
78
    protected function getOperationTypeNode(
79
        SchemaInterface $schema,
80
        TypeInterface $type,
81
        string $operation
82
    ): ?NodeInterface {
83
        /** @var SchemaDefinitionNode $node */
84
        $node = $schema->getAstNode();
85
86
        if (null === $node) {
87
            return $type->getAstNode();
0 ignored issues
show
Bug introduced by
The method getAstNode() does not exist on Digia\GraphQL\Type\Definition\TypeInterface. It seems like you code against a sub-type of Digia\GraphQL\Type\Definition\TypeInterface such as Digia\GraphQL\Type\Definition\InputObjectType or Digia\GraphQL\Type\Definition\ObjectType or Digia\GraphQL\Type\Definition\ScalarType or Digia\GraphQL\Type\Definition\EnumType or Digia\GraphQL\Type\Definition\InterfaceType or Digia\GraphQL\Type\Definition\UnionType. ( Ignorable by Annotation )

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

87
            return $type->/** @scrutinizer ignore-call */ getAstNode();
Loading history...
88
        }
89
90
        /** @var OperationTypeDefinitionNode $operationTypeNode */
91
        $operationTypeNode = find(
92
            $node->getOperationTypes(),
93
            function (OperationTypeDefinitionNode $operationType) use ($operation) {
94
                return $operationType->getOperation() === $operation;
95
            }
96
        );
97
98
        return $operationTypeNode->getType();
99
    }
100
}
101