Compiler::createVariablesContext()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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