ClassMetadataBuilder::build()   B
last analyzed

Complexity

Conditions 7
Paths 9

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 13
c 1
b 0
f 0
nc 9
nop 0
dl 0
loc 26
ccs 14
cts 14
cp 1
crap 7
rs 8.8333
1
<?php
2
3
namespace Bdf\Serializer\Metadata\Builder;
4
5
use Bdf\Serializer\Metadata\ClassMetadata;
6
use Bdf\Serializer\Type\Type;
7
use Bdf\Serializer\Util\AccessorGuesser;
8
use ReflectionClass;
9
10
/**
11
 * ClassMetadata
12
 *
13
 * @author  Seb
14
 * @template T as object
15
 */
16
class ClassMetadataBuilder
17
{
18
    /**
19
     * The class reflection
20
     *
21
     * @var ReflectionClass<T>
22
     */
23
    private $reflection;
24
25
    /**
26
     * The properties normalizer
27
     *
28
     * @var PropertyMetadataBuilder[]
29
     */
30
    private $properties = [];
31
32
    /**
33
     * Does the properties use setter
34
     *
35
     * @var bool
36
     */
37
    private $useSetters = false;
38
39
    /**
40
     * Does the properties use getter
41
     *
42
     * @var bool
43
     */
44
    private $useGetters = false;
45
46
    /**
47
     * The method to call on denormalization
48
     *
49
     * @var string|null
50
     */
51
    private $postDenormalization;
52
53
    /**
54
     * ClassMetadataBuilder constructor.
55
     *
56
     * @param ReflectionClass<T> $reflection
57
     */
58 198
    public function __construct(ReflectionClass $reflection)
59
    {
60 198
        $this->reflection = $reflection;
61
    }
62
63
    /**
64
     * Build the class normalizer
65
     *
66
     * @return ClassMetadata<T>
67
     */
68 196
    public function build(): ClassMetadata
69
    {
70 196
        $metadata = new ClassMetadata($this->reflection->getName());
71
72 196
        $alias = [];
73
74 196
        foreach ($this->properties as $name => $property) {
75 190
            if ($propertyAlias = $property->getAlias()) {
76 52
                $alias[$propertyAlias] = $name;
77
            }
78
79 190
            if ($this->useGetters && $method = AccessorGuesser::guessGetter($metadata->name, $name)) {
80 4
                $property->readWith($method);
81
            }
82
83 190
            if ($this->useSetters && $method = AccessorGuesser::guessSetter($metadata->name, $name)) {
84 4
                $property->writeWith($method);
85
            }
86
87 190
            $metadata->addProperty($property->build());
88
        }
89
90 196
        $metadata->setPropertyAliases($alias);
91 196
        $metadata->setPostDenormalization($this->postDenormalization);
92
93 196
        return $metadata;
94
    }
95
96
    /**
97
     * Get the class name
98
     *
99
     * @return string
100
     */
101
    public function name(): string
102
    {
103
        return $this->reflection->name;
104
    }
105
106
    /**
107
     * Set the normalizer class name
108
     *
109
     * @param string $class
110
     *
111
     * @return $this
112
     *
113
     * @todo Allow the metadata to choose its normalize to use ?
114
     */
115
//    public function normalizerClass($class)
116
//    {
117
//        $this->normalizerClass = $class;
118
//
119
//        return $this;
120
//    }
121
122
    /**
123
     * Set the callback for post denormalization
124
     *
125
     * @param string $method
126
     *
127
     * @return $this
128
     */
129 6
    public function postDenormalization(string $method)
130
    {
131 6
        $this->postDenormalization = $method;
132
133 6
        return $this;
134
    }
135
136
    /**
137
     * Enable setter on all properties
138
     *
139
     * @param boolean $flag
140
     *
141
     * @return $this
142
     */
143 6
    public function useSetters(bool $flag = true)
144
    {
145 6
        $this->useSetters = $flag;
146
147 6
        return $this;
148
    }
149
150
    /**
151
     * Enable getter on all properties
152
     *
153
     * @param boolean $flag
154
     *
155
     * @return $this
156
     */
157 6
    public function useGetters(bool $flag = true)
158
    {
159 6
        $this->useGetters = $flag;
160
161 6
        return $this;
162
    }
163
164
    /**
165
     * Get a property normalizer
166
     *
167
     * @param string $name
168
     *
169
     * @return PropertyMetadataBuilder
170
     */
171 4
    public function property(string $name)
172
    {
173 4
        if (isset($this->properties[$name])) {
174 2
            return $this->properties[$name];
175
        }
176
177 2
        return $this->add($name);
178
    }
179
180
    /**
181
     * Add a property normalizer
182
     *
183
     * @param string $name
184
     * @param string $type
185
     * @param array  $options
186
     *
187
     * @return PropertyMetadataBuilder
188
     */
189 190
    public function add(string $name, string $type = null, array $options = [])
190
    {
191 190
        $property = new PropertyMetadataBuilder($this->reflection, $name);
192 190
        $property->type($type);
193
194 190
        return $this->properties[$name] = $property->configure($options);
195
    }
196
197
    /**
198
     * Add a array property
199
     *
200
     * @param string $name
201
     * @param array  $options
202
     *
203
     * @return PropertyMetadataBuilder
204
     */
205 2
    public function collection($name, array $options = [])
206
    {
207 2
        return $this->add($name, Type::TARRAY, $options);
208
    }
209
210
    /**
211
     * Add a string property
212
     *
213
     * @param string $name
214
     * @param array  $options
215
     *
216
     * @return PropertyMetadataBuilder
217
     */
218 84
    public function string($name, array $options = [])
219
    {
220 84
        return $this->add($name, Type::STRING, $options);
221
    }
222
223
    /**
224
     * Add a integer property
225
     *
226
     * @param string $name
227
     * @param array  $options
228
     *
229
     * @return PropertyMetadataBuilder
230
     */
231 68
    public function integer($name, array $options = [])
232
    {
233 68
        return $this->add($name, Type::INTEGER, $options);
234
    }
235
236
    /**
237
     * Add a boolean property
238
     *
239
     * @param string $name
240
     * @param array  $options
241
     *
242
     * @return PropertyMetadataBuilder
243
     */
244 2
    public function boolean($name, array $options = [])
245
    {
246 2
        return $this->add($name, Type::BOOLEAN, $options);
247
    }
248
249
    /**
250
     * Add a float property
251
     *
252
     * @param string $name
253
     * @param array  $options
254
     *
255
     * @return PropertyMetadataBuilder
256
     */
257 2
    public function float($name, array $options = [])
258
    {
259 2
        return $this->add($name, Type::FLOAT, $options);
260
    }
261
262
    /**
263
     * Add a null property
264
     *
265
     * @param string $name
266
     * @param array  $options
267
     *
268
     * @return PropertyMetadataBuilder
269
     */
270 2
    public function null($name, array $options = [])
271
    {
272 2
        return $this->add($name, Type::TNULL, $options);
273
    }
274
275
    /**
276
     * Add a mixed property. The property type will be guessed by the value
277
     *
278
     * @param string $name
279
     * @param array  $options
280
     *
281
     * @return PropertyMetadataBuilder
282
     */
283 2
    public function mixed($name, array $options = [])
284
    {
285 2
        return $this->add($name, Type::MIXED, $options);
286
    }
287
288
    /**
289
     * Add a stdClass property
290
     *
291
     * @param string $name
292
     * @param array  $options
293
     *
294
     * @return PropertyMetadataBuilder
295
     */
296 2
    public function object($name, array $options = [])
297
    {
298 2
        return $this->add($name, \stdClass::class, $options);
299
    }
300
301
    /**
302
     * Add a DateTime property
303
     *
304
     * @param string $name
305
     * @param array  $options
306
     *
307
     * @return PropertyMetadataBuilder
308
     */
309 10
    public function dateTime($name, array $options = [])
310
    {
311 10
        return $this->add($name, \DateTime::class, $options);
312
    }
313
314
    /**
315
     * Add a DateTimeImmutable property
316
     *
317
     * @param string $name
318
     * @param array  $options
319
     *
320
     * @return PropertyMetadataBuilder
321
     */
322 2
    public function dateTimeImmutable($name, array $options = [])
323
    {
324 2
        return $this->add($name, \DateTimeImmutable::class, $options);
325
    }
326
}
327