Passed
Push — master ( 81686d...1595cb )
by Kirill
04:41
created

Compiler::rebuild()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file is part of Railt package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Railt\SDL;
13
14
use GraphQL\Contracts\TypeSystem\SchemaInterface;
15
use Phplrt\Contracts\Parser\ParserInterface;
16
use Phplrt\Source\Exception\NotFoundException;
17
use Phplrt\Source\Exception\NotReadableException;
18
use Psr\Log\LoggerAwareTrait;
19
use Psr\Log\LoggerInterface;
20
use Psr\SimpleCache\CacheInterface;
21
use Psr\SimpleCache\InvalidArgumentException;
22
use Railt\SDL\Backend\Context;
23
use Railt\SDL\Backend\Linker\LinkerFacadeTrait;
24
use Railt\SDL\Backend\Linker\LinkerInterface;
25
use Railt\SDL\Backend\Linker\Registry;
26
use Railt\SDL\Frontend\Generator;
27
use Railt\SDL\Spec\Railt;
28
use Railt\SDL\Spec\SpecificationInterface;
29
use Railt\TypeSystem\Schema;
30
31
/**
32
 * Class Compiler
33
 */
34
final class Compiler implements CompilerInterface
35
{
36
    use LinkerFacadeTrait;
37
    use LoggerAwareTrait;
38
39
    /**
40
     * @var bool
41
     */
42
    private bool $booted = false;
43
44
    /**
45
     * @var ParserInterface
46
     */
47
    private ParserInterface $frontend;
48
49
    /**
50
     * @var Context
51
     */
52
    private Context $context;
53
54
    /**
55
     * @var SpecificationInterface
56
     */
57
    private SpecificationInterface $spec;
58
59
    /**
60
     * @var LinkerInterface
61
     */
62
    private LinkerInterface $linker;
63
64
    /**
65
     * Compiler constructor.
66
     *
67
     * @param SpecificationInterface $spec
68
     * @param CacheInterface|null $cache
69
     * @param LoggerInterface|null $logger
70
     * @throws \Throwable
71
     */
72
    public function __construct(
73
        SpecificationInterface $spec = null,
74
        CacheInterface $cache = null,
75
        LoggerInterface $logger = null
76
    ) {
77
        $this->context = new Context();
78
        $this->spec = $spec ?? new Railt();
79
        $this->logger = $logger;
80
        $this->frontend = new Frontend($cache);
81
        $this->linker = new Registry();
82
    }
83
84
    /**
85
     * @return LinkerInterface
86
     */
87
    public function getLinker(): LinkerInterface
88
    {
89
        return $this->linker;
90
    }
91
92
    /**
93
     * @return Context
94
     */
95
    public function getContext(): Context
96
    {
97
        return $this->context;
98
    }
99
100
    /**
101
     * {@inheritDoc}
102
     * @throws \Throwable
103
     * @throws InvalidArgumentException
104
     */
105
    public function preload($source, array $variables = []): self
106
    {
107
        $this->bootIfNotBooted();
108
109
        $this->backend($this->frontend($source), $this->context, $variables);
110
111
        return $this;
112
    }
113
114
    /**
115
     * @return void
116
     * @throws NotFoundException
117
     * @throws NotReadableException
118
     */
119
    private function bootIfNotBooted(): void
120
    {
121
        if ($this->booted === false) {
122
            $this->booted = true;
123
124
            $this->spec->load($this);
125
        }
126
    }
127
128
    /**
129
     * @param iterable $ast
130
     * @param Context $ctx
131
     * @param array $variables
132
     * @return SchemaInterface
133
     * @throws \Throwable
134
     */
135
    private function backend(iterable $ast, Context $ctx, array $variables = []): SchemaInterface
136
    {
137
        $executor = new Backend($this->spec, $ctx, $this->linker);
138
139
        return $executor->run($ast, $variables);
140
    }
141
142
    /**
143
     * @param mixed $source
144
     * @return iterable
145
     * @throws InvalidArgumentException
146
     * @throws \Throwable
147
     */
148
    private function frontend($source): iterable
149
    {
150
        return $this->frontend->parse($source);
151
    }
152
153
    /**
154
     * {@inheritDoc}
155
     * @throws \Throwable
156
     * @throws InvalidArgumentException
157
     */
158
    public function compile($source, array $variables = []): SchemaInterface
159
    {
160
        $this->bootIfNotBooted();
161
162
        return $this->backend($this->frontend($source), clone $this->context, $variables);
163
    }
164
165
    /**
166
     * @return void
167
     * @throws NotFoundException
168
     * @throws NotReadableException
169
     * @throws \Throwable
170
     */
171
    public function rebuild(): void
172
    {
173
        (new Generator())->generateAndSave();
174
    }
175
}
176