Passed
Push — master ( 7defe8...edb967 )
by Vincent
25:00
created

PropertyMetadataBuilder::configure()   B

Complexity

Conditions 10
Paths 10

Size

Total Lines 41
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 11.5625

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 23
c 1
b 0
f 0
nc 10
nop 1
dl 0
loc 41
ccs 18
cts 24
cp 0.75
crap 11.5625
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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