Test Setup Failed
Push — master ( b48cec...128107 )
by Kirill
02:20
created

Factory   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 14
eloc 38
c 1
b 0
f 0
dl 0
loc 119
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A fetch() 0 11 3
A fetchDirective() 0 11 3
A __construct() 0 3 1
A loadFrom() 0 15 4
A build() 0 3 1
A builder() 0 9 2
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\SDL\Builder;
11
12
use Railt\SDL\Document;
13
use Railt\SDL\Executor\Registry;
14
use Railt\SDL\Ast\DefinitionNode;
15
use Railt\SDL\Ast\Definition\FieldDefinitionNode;
16
use Railt\SDL\Ast\Definition\SchemaDefinitionNode;
17
use GraphQL\Contracts\TypeSystem\Type\TypeInterface;
18
use GraphQL\Contracts\TypeSystem\DirectiveInterface;
19
use Railt\SDL\Ast\Definition\EnumTypeDefinitionNode;
20
use Railt\SDL\Ast\Definition\ArgumentDefinitionNode;
21
use GraphQL\Contracts\TypeSystem\DefinitionInterface;
22
use Railt\SDL\Ast\Definition\DirectiveDefinitionNode;
23
use Railt\SDL\Ast\Definition\EnumValueDefinitionNode;
24
use Railt\SDL\Ast\Definition\UnionTypeDefinitionNode;
25
use Railt\SDL\Ast\Definition\ObjectTypeDefinitionNode;
26
use Railt\SDL\Ast\Definition\ScalarTypeDefinitionNode;
27
use Railt\SDL\Ast\Definition\InputFieldDefinitionNode;
28
use Railt\SDL\Ast\Definition\InterfaceTypeDefinitionNode;
29
use Railt\SDL\Ast\Definition\InputObjectTypeDefinitionNode;
30
31
/**
32
 * Class Factory
33
 */
34
class Factory
35
{
36
    /**
37
     * @var string|TypeBuilder
38
     */
39
    private const TYPE_MAPPINGS = [
40
        // Definitions
41
        ArgumentDefinitionNode::class        => ArgumentBuilder::class,
42
        DirectiveDefinitionNode::class       => DirectiveBuilder::class,
43
        EnumValueDefinitionNode::class       => EnumValueBuilder::class,
44
        FieldDefinitionNode::class           => FieldBuilder::class,
45
        InputFieldDefinitionNode::class      => InputFieldBuilder::class,
46
        SchemaDefinitionNode::class          => SchemaBuilder::class,
47
48
        // TypeDefinitions
49
        EnumTypeDefinitionNode::class        => EnumTypeBuilder::class,
50
        InputObjectTypeDefinitionNode::class => InputObjectTypeBuilder::class,
51
        InterfaceTypeDefinitionNode::class   => InterfaceTypeBuilder::class,
52
        ObjectTypeDefinitionNode::class      => ObjectTypeBuilder::class,
53
        ScalarTypeDefinitionNode::class      => ScalarTypeBuilder::class,
54
        UnionTypeDefinitionNode::class       => UnionTypeBuilder::class,
55
    ];
56
57
    /**
58
     * @var Document
59
     */
60
    private Document $dictionary;
61
62
    /**
63
     * Builder constructor.
64
     *
65
     * @param Document $dictionary
66
     */
67
    public function __construct(Document $dictionary)
68
    {
69
        $this->dictionary = $dictionary;
70
    }
71
72
    /**
73
     * @param Registry $registry
74
     * @return Document
75
     */
76
    public function loadFrom(Registry $registry): Document
77
    {
78
        foreach ($registry->typeMap as $name => $typeNode) {
79
            $this->fetch($name, $registry);
80
        }
81
82
        foreach ($registry->directives as $name => $directiveNode) {
83
            $this->fetchDirective($name, $registry);
84
        }
85
86
        if ($registry->schema) {
87
            $this->dictionary->schema = $this->build($registry->schema, $registry);
88
        }
89
90
        return $this->dictionary;
91
    }
92
93
    /**
94
     * @param string $type
95
     * @param Registry $registry
96
     * @return TypeInterface
97
     */
98
    public function fetch(string $type, Registry $registry): TypeInterface
99
    {
100
        if (isset($this->dictionary->typeMap[$type])) {
101
            return $this->dictionary->typeMap[$type];
102
        }
103
104
        if (isset($registry->typeMap[$type])) {
105
            return $this->build($registry->typeMap[$type], $registry);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->build($reg...eMap[$type], $registry) returns the type GraphQL\Contracts\TypeSystem\DefinitionInterface which includes types incompatible with the type-hinted return GraphQL\Contracts\TypeSystem\Type\TypeInterface.
Loading history...
106
        }
107
108
        throw new \LogicException('Can not build type ' . $type);
109
    }
110
111
    /**
112
     * @param DefinitionNode $node
113
     * @param Registry $registry
114
     * @return DefinitionInterface
115
     */
116
    public function build(DefinitionNode $node, Registry $registry): DefinitionInterface
117
    {
118
        return $this->builder($node, $registry)->build();
119
    }
120
121
    /**
122
     * @param DefinitionNode $node
123
     * @param Registry $registry
124
     * @return TypeBuilder
125
     */
126
    private function builder(DefinitionNode $node, Registry $registry): TypeBuilder
127
    {
128
        $builder = self::TYPE_MAPPINGS[\get_class($node)] ?? null;
129
130
        if ($builder === null) {
131
            throw new \LogicException('Unrecognized builder for node ' . \get_class($node));
132
        }
133
134
        return new $builder($this, $registry, $this->dictionary, $node);
135
    }
136
137
    /**
138
     * @param string $type
139
     * @param Registry $registry
140
     * @return DirectiveInterface
141
     */
142
    public function fetchDirective(string $type, Registry $registry): DirectiveInterface
143
    {
144
        if (isset($this->dictionary->directives[$type])) {
145
            return $this->dictionary->directives[$type];
146
        }
147
148
        if (isset($registry->directives[$type])) {
149
            return $this->build($registry->directives[$type], $registry);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->build($reg...ives[$type], $registry) returns the type GraphQL\Contracts\TypeSystem\DefinitionInterface which includes types incompatible with the type-hinted return GraphQL\Contracts\TypeSystem\DirectiveInterface.
Loading history...
150
        }
151
152
        throw new \LogicException('Can not build directive ' . $type);
153
    }
154
}
155