Passed
Pull Request — master (#190)
by Sebastian
03:29
created

RootTypesRule::getOperationTypeNode()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 3
1
<?php
2
3
namespace Digia\GraphQL\Schema\Validation\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\Schema\SchemaInterface;
10
use Digia\GraphQL\Type\Definition\ObjectType;
11
use Digia\GraphQL\Type\Definition\TypeInterface;
12
use function Digia\GraphQL\Util\find;
13
14
class RootTypesRule extends AbstractRule
15
{
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(
40
        ?TypeInterface $rootType,
41
        string $operation
42
    ): void {
43
        $schema = $this->context->getSchema();
44
45
        if ($operation === 'query' && null === $rootType) {
46
            $this->context->reportError(
47
                new SchemaValidationException(
48
                    \sprintf('%s root type must be provided.',
49
                        \ucfirst($operation)),
50
                    $schema->hasAstNode() ? [$schema->getAstNode()] : null
51
                )
52
            );
53
54
            return;
55
        }
56
57
        if (null !== $rootType && !($rootType instanceof ObjectType)) {
58
            $this->context->reportError(
59
                new SchemaValidationException(
60
                    \sprintf(
61
                        $operation === 'query'
62
                            ? '%s root type must be Object type, it cannot be %s.'
63
                            : '%s root type must be Object type if provided, it cannot be %s.',
64
                        \ucfirst($operation),
65
                        (string)$rootType
66
                    ),
67
                    null !== $rootType ? [
68
                        $this->getOperationTypeNode($schema, $rootType,
69
                            $operation),
70
                    ] : null
71
                )
72
            );
73
74
            return;
75
        }
76
    }
77
78
    /**
79
     * @param SchemaInterface $schema
80
     * @param TypeInterface|ObjectType $type
81
     * @param string $operation
82
     *
83
     * @return NodeInterface|null
84
     */
85
    protected function getOperationTypeNode(
86
        SchemaInterface $schema,
87
        TypeInterface $type,
88
        string $operation
89
    ): ?NodeInterface
90
    {
91
        /** @var SchemaDefinitionNode $node */
92
        $node = $schema->getAstNode();
93
94
        if (null === $node) {
95
            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

95
            return $type->/** @scrutinizer ignore-call */ getAstNode();
Loading history...
96
        }
97
98
        /** @var OperationTypeDefinitionNode $operationTypeNode */
99
        $operationTypeNode = find(
100
            $node->getOperationTypes(),
101
            function (OperationTypeDefinitionNode $operationType) use (
102
                $operation
103
            ) {
104
                return $operationType->getOperation() === $operation;
105
            }
106
        );
107
108
        return $operationTypeNode->getType();
109
    }
110
}
111