Issues (158)

src/SchemaBuilder.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Jerowork\GraphqlAttributeSchema;
6
7
use GraphQL\Type\Definition\ListOfType;
8
use GraphQL\Type\Definition\NonNull;
9
use GraphQL\Type\Definition\ObjectType;
10
use GraphQL\Type\Definition\Type;
11
use GraphQL\Type\Schema;
12
use Jerowork\GraphqlAttributeSchema\Node\MutationNode;
13
use Jerowork\GraphqlAttributeSchema\Node\QueryNode;
14
use Jerowork\GraphqlAttributeSchema\Node\TypeReference\ObjectTypeReference;
15
use Jerowork\GraphqlAttributeSchema\Resolver\BuiltTypesRegistry;
16
use Jerowork\GraphqlAttributeSchema\Resolver\RootTypeResolver;
17
use Jerowork\GraphqlAttributeSchema\Resolver\Type\TypeResolverSelector;
18
19
final readonly class SchemaBuilder
0 ignored issues
show
A parse error occurred: Syntax error, unexpected T_READONLY, expecting T_CLASS on line 19 at column 6
Loading history...
20
{
21 3
    public function __construct(
22
        private AstContainer $astContainer,
23
        private BuiltTypesRegistry $builtTypesRegistry,
24
        private TypeResolverSelector $typeResolverSelector,
25
        private RootTypeResolver $rootTypeResolver,
26 3
    ) {}
27
28
    /**
29
     * @throws SchemaBuildException
30
     */
31 3
    public function build(Ast $ast): Schema
32
    {
33 3
        $this->astContainer->setAst($ast);
34
35 3
        $queries = array_map(fn($node) => $this->rootTypeResolver->createType($node), $ast->getNodesByNodeType(QueryNode::class));
36
37 3
        if ($queries === []) {
38 1
            throw SchemaBuildException::missingQueries();
39
        }
40
41 2
        $mutations = array_map(fn($node) => $this->rootTypeResolver->createType($node), $ast->getNodesByNodeType(MutationNode::class));
42
43 2
        if ($mutations === []) {
44 1
            throw SchemaBuildException::missingMutations();
45
        }
46
47 1
        return new Schema([
48 1
            'query' => new ObjectType([
49 1
                'name' => 'Query',
50 1
                'fields' => $queries,
51 1
            ]),
52 1
            'mutation' => new ObjectType([
53 1
                'name' => 'Mutation',
54 1
                'fields' => $mutations,
55 1
            ]),
56 1
            'types' => $this->getTypesImplementingInterface(),
57 1
        ]);
58
    }
59
60
    /**
61
     * Get all types implementing an interface.
62
     * When an implementation is not defined in a schema, it's not automatically loaded by the resolvers.
63
     * Therefore, load all interface implementation types on the root schema level as well.
64
     *
65
     * @return iterable<Closure(): Type>
66
     */
67 1
    private function getTypesImplementingInterface(): iterable
68
    {
69 1
        foreach ($this->astContainer->getAst()->getNodesImplementingInterface() as $node) {
70 1
            $typeReference = ObjectTypeReference::create($node->getClassName());
71
72 1
            if ($this->builtTypesRegistry->hasType($node->getClassName())) {
73
                continue;
74
            }
75
76 1
            $type = $this->typeResolverSelector->getResolver($typeReference)->createType($typeReference);
77
78 1
            if ($type instanceof NonNull) {
79 1
                $type = $type->getWrappedType();
80
            }
81
82 1
            if ($type instanceof ListOfType) {
83
                $type = $type->getWrappedType();
84
85
                if ($type instanceof NonNull) {
86
                    $type = $type->getWrappedType();
87
                }
88
            }
89
90 1
            $this->builtTypesRegistry->addType($node->getClassName(), $type);
91
92 1
            yield fn() => $type;
93
        }
94
    }
95
}
96