Passed
Pull Request — master (#173)
by Christoffer
03:13
created

SchemaBuilder::getOperationTypeDefinitions()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
c 0
b 0
f 0
rs 8.5806
cc 4
eloc 13
nc 4
nop 2
1
<?php
2
3
namespace Digia\GraphQL\Schema\Building;
4
5
use Digia\GraphQL\Error\BuildingException;
6
use Digia\GraphQL\Language\Node\DirectiveDefinitionNode;
7
use Digia\GraphQL\Language\Node\DocumentNode;
8
use Digia\GraphQL\Language\Node\NamedTypeNode;
9
use Digia\GraphQL\Language\Node\SchemaDefinitionNode;
10
use Digia\GraphQL\Language\Node\TypeDefinitionNodeInterface;
11
use Digia\GraphQL\Language\Node\TypeNodeInterface;
12
use Digia\GraphQL\Schema\DefinitionBuilder;
13
use Digia\GraphQL\Schema\ResolverRegistryInterface;
14
use Digia\GraphQL\Schema\SchemaInterface;
15
use Psr\SimpleCache\CacheInterface;
16
use function Digia\GraphQL\Type\newSchema;
17
18
class SchemaBuilder implements SchemaBuilderInterface
19
{
20
    /**
21
     * @var CacheInterface
22
     */
23
    protected $cache;
24
25
    /**
26
     * BuilderContextCreator constructor.
27
     * @param CacheInterface $cache
28
     */
29
    public function __construct(CacheInterface $cache)
30
    {
31
        $this->cache = $cache;
32
    }
33
34
    /**
35
     * @inheritdoc
36
     */
37
    public function build(
38
        DocumentNode $document,
39
        ResolverRegistryInterface $resolverRegistry,
40
        array $options = []
41
    ): SchemaInterface {
42
        $context = $this->createContext($document, $resolverRegistry);
43
44
        return newSchema([
45
            'query'        => $context->buildQueryType(),
46
            'mutation'     => $context->buildMutationType(),
47
            'subscription' => $context->buildSubscriptionType(),
48
            'types'        => $context->buildTypes(),
49
            'directives'   => $context->buildDirectives(),
50
            'astNode'      => $context->getSchemaDefinition(),
51
            'assumeValid'  => $options['assumeValid'] ?? false,
52
        ]);
53
    }
54
55
    /**
56
     * @inheritdoc
57
     */
58
    public function createContext(
59
        DocumentNode $document,
60
        ResolverRegistryInterface $resolverRegistry
61
    ): BuildingContextInterface {
62
        $info = $this->createInfo($document);
63
64
        $definitionBuilder = new DefinitionBuilder(
65
            $info->getTypeDefinitionMap(),
66
            $resolverRegistry,
67
            null, // use the default resolveType-function
68
            $this->cache
69
        );
70
71
        return new BuildingContext($resolverRegistry, $definitionBuilder, $info);
72
    }
73
74
    /**
75
     * @inheritdoc
76
     * @throws BuildingException
77
     */
78
    protected function createInfo(DocumentNode $document): BuildInfo
79
    {
80
        $schemaDefinition     = null;
81
        $typeDefinitionMap    = [];
82
        $directiveDefinitions = [];
83
84
        foreach ($document->getDefinitions() as $definition) {
85
            if ($definition instanceof SchemaDefinitionNode) {
86
                if (null !== $schemaDefinition) {
87
                    throw new BuildingException('Must provide only one schema definition.');
88
                }
89
90
                $schemaDefinition = $definition;
91
92
                continue;
93
            }
94
95
            if ($definition instanceof TypeDefinitionNodeInterface) {
96
                $typeName = $definition->getNameValue();
97
98
                if (isset($typeDefinitionMap[$typeName])) {
99
                    throw new BuildingException(sprintf('Type "%s" was defined more than once.', $typeName));
100
                }
101
102
                $typeDefinitionMap[$typeName] = $definition;
103
104
                continue;
105
            }
106
107
            if ($definition instanceof DirectiveDefinitionNode) {
108
                $directiveDefinitions[] = $definition;
109
110
                continue;
111
            }
112
        }
113
114
        return new BuildInfo(
115
            $document,
116
            $typeDefinitionMap,
117
            $directiveDefinitions,
118
            null !== $schemaDefinition ? $this->getOperationTypeDefinitions($schemaDefinition, $typeDefinitionMap) : [],
119
            $schemaDefinition
120
        );
121
    }
122
123
    /**
124
     * @param SchemaDefinitionNode $node
125
     * @return array
126
     * @throws BuildingException
127
     */
128
    protected function getOperationTypeDefinitions(SchemaDefinitionNode $node, array $typeDefinitionMap): array
129
    {
130
        $definitions = [];
131
132
        foreach ($node->getOperationTypes() as $operationTypeDefinition) {
133
            /** @var TypeNodeInterface|NamedTypeNode $operationType */
134
            $operationType = $operationTypeDefinition->getType();
135
            $typeName      = $operationType->getNameValue();
0 ignored issues
show
Bug introduced by
The method getNameValue() does not exist on Digia\GraphQL\Language\Node\TypeNodeInterface. It seems like you code against a sub-type of Digia\GraphQL\Language\Node\TypeNodeInterface such as Digia\GraphQL\Language\Node\NamedTypeNode. ( Ignorable by Annotation )

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

135
            /** @scrutinizer ignore-call */ 
136
            $typeName      = $operationType->getNameValue();
Loading history...
136
            $operation     = $operationTypeDefinition->getOperation();
137
138
            if (isset($definitions[$typeName])) {
139
                throw new BuildingException(
140
                    \sprintf('Must provide only one %s type in schema.', $operation)
141
                );
142
            }
143
144
            if (!isset($typeDefinitionMap[$typeName])) {
145
                throw new BuildingException(
146
                    \sprintf('Specified %s type %s not found in document.', $operation, $typeName)
147
                );
148
            }
149
150
            $definitions[$operation] = $operationType;
151
        }
152
153
        return $definitions;
154
    }
155
}
156