Completed
Push — master ( 7d754d...8e6df6 )
by Sébastien
04:12
created

PropertyMetadataBuilder::inline()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Bdf\Serializer\Metadata\Builder;
4
5
use Bdf\Serializer\Context\DenormalizationContext;
6
use Bdf\Serializer\Context\NormalizationContext;
7
use Bdf\Serializer\Metadata\PropertyMetadata;
8
use Bdf\Serializer\PropertyAccessor\PropertyAccessorInterface;
9
use Bdf\Serializer\Type\TypeFactory;
10
use Bdf\Serializer\Util\AccessorGuesser;
11
use ReflectionClass;
12
13
/**
14
 * PropertyMetadataBuilder
15
 * 
16
 * @author  Seb
17
 */
18
class PropertyMetadataBuilder
19
{
20
    /**
21
     * The owner reflection class
22
     *
23
     * @var ReflectionClass
24
     */
25
    private $reflection;
26
27
    /**
28
     * The property name
29
     *
30
     * @var string
31
     */
32
    private $name;
33
34
    /**
35
     * The property alias
36
     *
37
     * @var string
38
     */
39
    private $alias;
40
41
    /**
42
     * The property type
43
     *
44
     * @var string
45
     */
46
    private $type;
47
48
    /**
49
     * The property groups
50
     *
51
     * @var array
52
     */
53
    private $groups = [];
54
55
    /**
56
     * The property accessor
57
     *
58
     * @var PropertyAccessorInterface|array
59
     */
60
    private $accessor;
61
62
    /**
63
     * The version when the property has been added.
64
     *
65
     * @var string
66
     */
67
    private $since;
68
69
    /**
70
     * The version when the property has been removed.
71
     *
72
     * @var string
73
     */
74
    private $until;
75
76
    /**
77
     * The read only state of the property.
78
     *
79
     * @var bool
80
     */
81
    private $readOnly;
82
83
    /**
84
     * The inline state of the property.
85
     *
86
     * @var bool
87
     */
88
    private $inline;
89
90
    /**
91
     * The context options for normalization.
92
     *
93
     * @var null|array
94
     */
95
    private $normalizationOptions;
96
97
    /**
98
     * The context options for denormalization.
99
     *
100
     * @var null|array
101
     */
102
    private $denormalizationOptions;
103
104
    /**
105
     * PropertyMetadataBuilder constructor.
106
     *
107
     * @param ReflectionClass $reflection
108
     * @param string $name
109
     */
110
    public function __construct(ReflectionClass $reflection, string $name)
111
    {
112
        $this->reflection = $reflection;
113
        $this->name = $name;
114
    }
115
116
    /**
117
     * Build the property metadata
118
     *
119
     * @return PropertyMetadata
120
     */
121
    public function build(): PropertyMetadata
122
    {
123
        $property = new PropertyMetadata($this->reflection->name, $this->name);
124
        $property->setType(TypeFactory::createType($this->type));
125
        $property->setAlias($this->alias ?: $this->name);
126
        $property->setGroups($this->groups);
127
        $property->setAccessor($this->buildAccessor($this->accessor));
128
        $property->setSince($this->since);
129
        $property->setUntil($this->until);
130
        $property->setReadOnly($this->readOnly === true);
131
        $property->setInline($this->inline === true);
132
        $property->setNormalizationOptions($this->normalizationOptions);
133
        $property->setDenormalizationOptions($this->denormalizationOptions);
134
135
        $defaultValues = $this->reflection->getDefaultProperties();
136
        if (isset($defaultValues[$this->name])) {
137
            $property->setDefaultValue($defaultValues[$this->name]);
138
        }
139
140
        return $property;
141
    }
142
143
    /**
144
     * Build the property accessor
145
     *
146
     * @param mixed $accessor
147
     *
148
     * @return PropertyAccessorInterface
149
     */
150
    private function buildAccessor($accessor): PropertyAccessorInterface
151
    {
152
        if ($accessor instanceof PropertyAccessorInterface) {
153
            return $accessor;
154
        }
155
156
        return AccessorGuesser::guessAccessor($this->reflection, $this->name, $accessor);
157
    }
158
159
    /**
160
     * Set the property type
161
     *
162
     * @param null|string $type
163
     *
164
     * @return $this
165
     */
166
    public function type(?string $type)
167
    {
168
        $this->type = $type;
169
170
        return $this;
171
    }
172
173
    /**
174
     * Set the property type as collection
175
     *
176
     * @return $this
177
     */
178
    public function collection()
179
    {
180
        $this->type .= '[]';
181
182
        return $this;
183
    }
184
185
    /**
186
     * Set the property type as collection of a given type
187
     *
188
     * @param string $subType
189
     *
190
     * @return $this
191
     */
192
    public function collectionOf($subType)
193
    {
194
        return $this->type($subType)->collection();
195
    }
196
197
    /**
198
     * Set the property type as collection wrapper of a given type
199
     *
200
     * @param string $subType
201
     *
202
     * @return $this
203
     */
204
    public function wrapperOf($subType)
205
    {
206
        $this->type .= "<$subType>";
207
208
        return $this;
209
    }
210
211
    /**
212
     * Set the property alias
213
     *
214
     * @param string $alias
215
     *
216
     * @return $this
217
     */
218
    public function alias($alias)
219
    {
220
        $this->alias = $alias;
221
222
        return $this;
223
    }
224
225
    /**
226
     * et the property alias
227
     *
228
     * @return string
229
     */
230
    public function getAlias(): ?string
231
    {
232
        return $this->alias;
233
    }
234
235
    /**
236
     * Set the property groups
237
     *
238
     * @param array $groups
239
     *
240
     * @return $this
241
     */
242
    public function groups(array $groups)
243
    {
244
        $this->groups = $groups;
245
246
        return $this;
247
    }
248
249
    /**
250
     * Add a property group
251
     *
252
     * @param string $group
253
     *
254
     * @return $this
255
     */
256
    public function addGroup(string $group)
257
    {
258
        $this->groups[] = $group;
259
260
        return $this;
261
    }
262
263
    /**
264
     * Set the property accessor
265
     *
266
     * @param PropertyAccessorInterface|array $accessor
267
     *
268
     * @return $this
269
     */
270
    public function accessor($accessor)
271
    {
272
        $this->accessor = $accessor;
273
274
        return $this;
275
    }
276
277
    /**
278
     * Set the property accessor
279
     *
280
     * A accessor as string will be considered as a method
281
     *
282
     * @param PropertyAccessorInterface|string $accessor
283
     *
284
     * @return $this
285
     */
286
    public function readWith($accessor)
287
    {
288
        $this->accessor['reader'] = $accessor;
289
290
        return $this;
291
    }
292
293
    /**
294
     * Set the property accessor
295
     *
296
     * @param PropertyAccessorInterface|string $accessor
297
     *
298
     * @return $this
299
     */
300
    public function writeWith($accessor)
301
    {
302
        $this->accessor['writer'] = $accessor;
303
304
        return $this;
305
    }
306
307
    /**
308
     * Set the version when the property has been added
309
     *
310
     * @param string $version
311
     *
312
     * @return $this
313
     */
314
    public function since(string $version)
315
    {
316
        $this->since = $version;
317
318
        return $this;
319
    }
320
321
    /**
322
     * Set the property read only.
323
     *
324
     * @param bool $flag
325
     *
326
     * @return $this
327
     */
328
    public function readOnly(bool $flag = true)
329
    {
330
        $this->readOnly = $flag;
331
332
        return $this;
333
    }
334
335
    /**
336
     * Set the property inline.
337
     * The properties of this property will be added as the same level.
338
     *
339
     * @param bool $flag
340
     *
341
     * @return $this
342
     */
343
    public function inline(bool $flag = true)
344
    {
345
        $this->inline = $flag;
346
347
        return $this;
348
    }
349
350
    /**
351
     * Set the version when the property has been removed
352
     *
353
     * @param string $version
354
     *
355
     * @return $this
356
     */
357
    public function until(string $version)
358
    {
359
        $this->until = $version;
360
361
        return $this;
362
    }
363
364
    /**
365
     * Add a normalization option
366
     *
367
     * @param string $option
368
     * @param string $value
369
     *
370
     * @return $this
371
     */
372
    public function normalization(string $option, $value)
373
    {
374
        $this->normalizationOptions[$option] = $value;
375
376
        return $this;
377
    }
378
379
    /**
380
     * Add a denormalization option
381
     *
382
     * @param string $option
383
     * @param string $value
384
     *
385
     * @return $this
386
     */
387
    public function denormalization(string $option, $value)
388
    {
389
        $this->denormalizationOptions[$option] = $value;
390
391
        return $this;
392
    }
393
394
    /**
395
     * Set the date time format
396
     *
397
     * @param string $format
398
     *
399
     * @return $this
400
     */
401
    public function dateFormat(string $format)
402
    {
403
        $this->normalization(NormalizationContext::DATETIME_FORMAT, $format);
404
        $this->denormalization(DenormalizationContext::DATETIME_FORMAT, $format);
405
406
        return $this;
407
    }
408
409
    /**
410
     * Set the internal date timezone
411
     *
412
     * @param string $timezone
413
     *
414
     * @return $this
415
     */
416
    public function timezone(string $timezone)
417
    {
418
        $this->denormalization(DenormalizationContext::TIMEZONE, $timezone);
419
420
        return $this;
421
    }
422
423
    /**
424
     * Set the serialized date timezone
425
     *
426
     * @param string $timezone
427
     *
428
     * @return $this
429
     */
430
    public function toTimezone(string $timezone)
431
    {
432
        $this->normalization(NormalizationContext::TIMEZONE, $timezone);
433
        $this->denormalization(DenormalizationContext::TIMEZONE_HINT, $timezone);
434
435
        return $this;
436
    }
437
438
    /**
439
     * The property will be normalize if its value is null
440
     *
441
     * @param bool $flag
442
     *
443
     * @return $this
444
     */
445
    public function conserveNull(bool $flag = true)
446
    {
447
        $this->normalization(NormalizationContext::NULL, $flag);
448
449
        return $this;
450
    }
451
452
    /**
453
     * Keep the default value of the property
454
     *
455
     * @param bool $flag
456
     *
457
     * @return $this
458
     */
459
    public function conserveDefault(bool $flag = false)
460
    {
461
        $this->normalization(NormalizationContext::REMOVE_DEFAULT_VALUE, $flag);
462
463
        return $this;
464
    }
465
466
    /**
467
     * Import options in the builder
468
     * Legacy method, should not be used
469
     *
470
     * @param array $values
471
     *
472
     * @return $this
473
     */
474
    public function configure(array $values)
475
    {
476
        foreach ($values as $property => $value) {
477
            switch ($property) {
478
                case 'type':
479
                    $this->type($value);
480
                    break;
481
                
482
                case 'group':
483
                case 'groups':
484
                    $this->groups((array)$value);
485
                    break;
486
487
                case 'alias':
488
                case 'serializedName':
489
                    $this->alias($value);
490
                    break;
491
492
                case 'since':
493
                    $this->since($value);
494
                    break;
495
496
                case 'until':
497
                    $this->until($value);
498
                    break;
499
500
                case 'readOnly':
501
                    $this->readOnly((bool)$value);
502
                    break;
503
504
//                case 'maxDepth':
505
//                    $this->$property = $value;
506
//                    break;
507
//
508
//                case 'inline':
509
//                    $this->$property = (bool)$value;
510
//                    break;
511
            }
512
        }
513
        
514
        return $this;
515
    }
516
}
517