-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMapper.php
211 lines (182 loc) · 6.13 KB
/
Mapper.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
<?php
declare(strict_types=1);
namespace TypeLang\Mapper;
use TypeLang\Mapper\Exception\Definition\TypeNotFoundException;
use TypeLang\Mapper\Platform\PlatformInterface;
use TypeLang\Mapper\Platform\Standard\Type\TypeInterface;
use TypeLang\Mapper\Platform\StandardPlatform;
use TypeLang\Mapper\Runtime\Configuration;
use TypeLang\Mapper\Runtime\Context\RootContext;
use TypeLang\Mapper\Runtime\Parser\InMemoryTypeParser;
use TypeLang\Mapper\Runtime\Parser\LoggableTypeParser;
use TypeLang\Mapper\Runtime\Parser\TraceableTypeParser;
use TypeLang\Mapper\Runtime\Parser\TypeParser;
use TypeLang\Mapper\Runtime\Parser\TypeParserFacade;
use TypeLang\Mapper\Runtime\Parser\TypeParserFacadeInterface;
use TypeLang\Mapper\Runtime\Repository\InMemoryTypeRepository;
use TypeLang\Mapper\Runtime\Repository\LoggableTypeRepository;
use TypeLang\Mapper\Runtime\Repository\TraceableTypeRepository;
use TypeLang\Mapper\Runtime\Repository\TypeRepository;
use TypeLang\Mapper\Runtime\Repository\TypeRepositoryFacade;
use TypeLang\Mapper\Runtime\Repository\TypeRepositoryFacadeInterface;
final class Mapper implements NormalizerInterface, DenormalizerInterface
{
private readonly TypeRepositoryFacadeInterface $types;
private readonly TypeParserFacadeInterface $parser;
public function __construct(
private readonly PlatformInterface $platform = new StandardPlatform(),
private readonly Configuration $config = new Configuration(),
) {
$this->parser = $this->createTypeParser($platform);
$this->types = $this->createTypeRepository($platform);
}
private function createTypeParser(PlatformInterface $platform): TypeParserFacadeInterface
{
$runtime = TypeParser::createFromPlatform($platform);
if (($tracer = $this->config->getTracer()) !== null) {
$runtime = new TraceableTypeParser($tracer, $runtime);
}
if (($logger = $this->config->getLogger()) !== null) {
$runtime = new LoggableTypeParser($logger, $runtime);
}
return new TypeParserFacade(new InMemoryTypeParser(
delegate: $runtime,
));
}
private function createTypeRepository(PlatformInterface $platform): TypeRepositoryFacadeInterface
{
$runtime = new InMemoryTypeRepository(
delegate: TypeRepository::createFromPlatform(
platform: $platform,
parser: $this->parser,
),
);
if (($tracer = $this->config->getTracer()) !== null) {
$runtime = new TraceableTypeRepository($tracer, $runtime);
}
if (($logger = $this->config->getLogger()) !== null) {
$runtime = new LoggableTypeRepository($logger, $runtime);
}
return new TypeRepositoryFacade(
parser: $this->parser,
runtime: $runtime,
);
}
/**
* Returns current mapper platform.
*
* @api
*/
public function getPlatform(): PlatformInterface
{
return $this->platform;
}
/**
* Returns current types registry.
*
* @api
*/
public function getTypes(): TypeRepositoryFacadeInterface
{
return $this->types;
}
/**
* Returns current types parser.
*
* @api
*/
public function getParser(): TypeParserFacadeInterface
{
return $this->parser;
}
public function normalize(mixed $value, ?string $type = null): mixed
{
$instance = $type === null
? $this->types->getTypeByValue($value)
: $this->types->getTypeByDefinition($type);
return $instance->cast($value, RootContext::forNormalization(
value: $value,
config: $this->config,
parser: $this->parser,
types: $this->types,
));
}
public function isNormalizable(mixed $value, ?string $type = null): bool
{
$instance = $type === null
? $this->types->getTypeByValue($value)
: $this->types->getTypeByDefinition($type);
return $instance->match($value, RootContext::forNormalization(
value: $value,
config: $this->config,
parser: $this->parser,
types: $this->types,
));
}
public function denormalize(mixed $value, string $type): mixed
{
$instance = $this->types->getTypeByDefinition($type);
return $instance->cast($value, RootContext::forDenormalization(
value: $value,
config: $this->config,
parser: $this->parser,
types: $this->types,
));
}
public function isDenormalizable(mixed $value, string $type): bool
{
$instance = $this->types->getTypeByDefinition($type);
return $instance->match($value, RootContext::forDenormalization(
value: $value,
config: $this->config,
parser: $this->parser,
types: $this->types,
));
}
/**
* Returns type for mapping by signature.
*
* @api
*
* @param non-empty-string $type
*
* @throws TypeNotFoundException in case of type not found
* @throws \Throwable in case of internal error occurs
*/
public function getType(string $type): TypeInterface
{
return $this->types->getTypeByDefinition($type);
}
/**
* Returns type for mapping by value.
*
* @api
*
* @throws TypeNotFoundException in case of type not found
* @throws \Throwable in case of internal error occurs
*/
public function getTypeByValue(mixed $value): TypeInterface
{
return $this->types->getTypeByValue($value);
}
/**
* Warms up the cache for the selected class or object.
*
* Please note that the cache can only be warmed up if the
* appropriate driver is used otherwise it doesn't give any effect.
*
* @api
*
* @param class-string|object $class
*
* @throws TypeNotFoundException
* @throws \Throwable
*/
public function warmup(string|object $class): void
{
if (\is_object($class)) {
$class = $class::class;
}
$this->types->getTypeByDefinition($class);
}
}