Test Setup Failed
Push — master ( 1595cb...050b68 )
by Kirill
21:00
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\LoggerInterface;
19
use Psr\SimpleCache\CacheInterface;
20
use Psr\SimpleCache\InvalidArgumentException;
21
use Railt\SDL\Backend\Context;
22
use Railt\SDL\Backend\HashTable;
23
use Railt\SDL\Backend\HashTableInterface;
24
use Railt\SDL\Compiler\ContextFacadeTrait;
25
use Railt\SDL\Compiler\DevelopmentModeFacadeTrait;
26
use Railt\SDL\Compiler\HashTableFacadeTrait;
27
use Railt\SDL\Compiler\LinkerFacadeTrait;
28
use Railt\SDL\Compiler\NameResolverFacadeTrait;
29
use Railt\SDL\Compiler\SpecificationFacadeTrait;
30
use Railt\SDL\Compiler\ValidatorFacadeTrait;
31
use Railt\SDL\Spec\SpecificationInterface;
32
33
/**
34
 * Class Compiler
35
 */
36
final class Compiler implements CompilerInterface
37
{
38
    use LinkerFacadeTrait;
39
    use ContextFacadeTrait;
40
    use HashTableFacadeTrait;
41
    use ValidatorFacadeTrait;
42
    use NameResolverFacadeTrait;
43
    use SpecificationFacadeTrait;
44
    use DevelopmentModeFacadeTrait;
45
46
    /**
47
     * @var bool
48
     */
49
    private bool $booted = false;
50
51
    /**
52
     * @var ParserInterface
53
     */
54
    private ParserInterface $frontend;
55
56
    /**
57
     * Compiler constructor.
58
     *
59
     * @param SpecificationInterface $spec
60
     * @param CacheInterface|null $cache
61
     * @param LoggerInterface|null $logger
62
     * @throws \Throwable
63
     */
64
    public function __construct(
65
        SpecificationInterface $spec = null,
66
        CacheInterface $cache = null,
67
        LoggerInterface $logger = null
68
    ) {
69
        $this->logger = $logger;
70
        $this->frontend = new Frontend($cache);
71
72
        $this->bootLinkerFacadeTrait();
73
        $this->bootContextFacadeTrait();
74
        $this->bootHashTableFacadeTrait();
75
        $this->bootValidatorFacadeTrait();
76
        $this->bootNameResolverFacadeTrait();
77
78
        $this->setSpecification($spec);
79
    }
80
81
    /**
82
     * {@inheritDoc}
83
     * @throws \Throwable
84
     * @throws InvalidArgumentException
85
     */
86
    public function preload($source, array $variables = []): self
87
    {
88
        $this->bootIfNotBooted();
89
90
        $this->backend($this->frontend($source), $this->context, $variables);
91
92
        return $this;
93
    }
94
95
    /**
96
     * @return void
97
     */
98
    private function bootIfNotBooted(): void
99
    {
100
        if ($this->booted === false) {
101
            $this->booted = true;
102
103
            $this->bootSpecificationFacadeTrait();
104
        }
105
    }
106
107
    /**
108
     * @param iterable $ast
109
     * @param Context $ctx
110
     * @param array $variables
111
     * @return SchemaInterface
112
     * @throws \Throwable
113
     */
114
    private function backend(iterable $ast, Context $ctx, array $variables = []): SchemaInterface
115
    {
116
        $hash = $this->createVariablesContext($variables);
117
118
        $executor = new Backend($this, $ctx);
119
120
        return $executor->run($ast, $hash);
121
    }
122
123
    /**
124
     * @param array $variables
125
     * @return HashTableInterface
126
     */
127
    private function createVariablesContext(array $variables = []): HashTableInterface
128
    {
129
        return new HashTable($this->getValueFactory(), $variables, $this->getVariables());
130
    }
131
132
    /**
133
     * @param mixed $source
134
     * @return iterable
135
     * @throws InvalidArgumentException
136
     * @throws \Throwable
137
     */
138
    private function frontend($source): iterable
139
    {
140
        return $this->frontend->parse($source);
141
    }
142
143
    /**
144
     * {@inheritDoc}
145
     * @throws \Throwable
146
     */
147
    public function compile($source, array $variables = []): SchemaInterface
148
    {
149
        $this->bootIfNotBooted();
150
151
        try {
152
            return $this->backend($this->frontend($source), clone $this->context, $variables);
153
        } catch (InvalidArgumentException $e) {
154
            throw new \InvalidArgumentException($e->getMessage());
155
        }
156
    }
157
}
158