Passed
Branch new_stuff (69e2c3)
by JHONATAN
03:08
created

Normalizer::extractData()   C

Complexity

Conditions 13
Paths 37

Size

Total Lines 52
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 13.2076

Importance

Changes 0
Metric Value
dl 0
loc 52
ccs 25
cts 28
cp 0.8929
rs 5.9687
c 0
b 0
f 0
cc 13
eloc 28
nc 37
nop 3
crap 13.2076

How to fix   Long Method    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 Vox\Serializer;
4
5
use Metadata\MetadataFactoryInterface;
6
use RuntimeException;
7
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
8
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
9
use Vox\Data\Mapping\Bindings;
10
use Vox\Data\Mapping\Exclude;
11
use Vox\Metadata\ClassMetadata;
12
use Vox\Metadata\PropertyMetadata;
13
14
/**
15
 * A data normalized aimed to be used with symfony serializer component
16
 * 
17
 * @author Jhonatan Teixeira <[email protected]>
18
 */
19
class Normalizer implements NormalizerInterface, NormalizerAwareInterface
20
{
21
    /**
22
     * @var MetadataFactoryInterface
23
     */
24
    private $metadataFactory;
25
26
    /**
27
     * @var NormalizerInterface
28
     */
29
    private $normalizer;
30
31
    /**
32
     * @var \SplObjectStorage
33
     */
34
    private $storage;
35
    
36 22
    public function __construct(MetadataFactoryInterface $metadataFactory)
37
    {
38 22
        $this->metadataFactory = $metadataFactory;
39 22
        $this->storage = new \SplObjectStorage();
40 22
    }
41
    
42 5
    public function normalize($object, $format = null, array $context = [])
43
    {
44 5
        if ($this->storage->offsetExists($object)) {
45
            return $this->storage[$object];
46
        }
47
48 5
        $data = $this->extractData($object, $format, $context);
49
50 5
        return $data;
51
    }
52
53 5
    private function extractData($object, string $format = null, array $context = []): array
54
    {
55 5
        $objectMetadata = $this->metadataFactory->getMetadataForClass(get_class($object));
56
57 5
        if (!$objectMetadata instanceof ClassMetadata) {
58
            throw new RuntimeException('invalid metadata class');
59
        }
60
61 5
        $data = [];
62
63 5
        if ($objectMetadata->reflection->getParentClass()) {
64
            $data['type'] = get_class($object);
65
        }
66
67
        /* @var $propertyMetadata PropertyMetadata */
68 5
        foreach ($objectMetadata->propertyMetadata as $propertyMetadata) {
69 5
            $binding = $propertyMetadata->getAnnotation(Bindings::class);
70 5
            $value   = $propertyMetadata->getValue($object);
71
72 5
            if ($propertyMetadata->hasAnnotation(Exclude::class)
73 5
                && $propertyMetadata->getAnnotation(Exclude::class)->output) {
74
                continue;
75
            }
76
77 5
            if (is_array($value)
78 5
                && (preg_match('/\[\]$/', $propertyMetadata->type) || $propertyMetadata->type == 'array')) {
79 1
                $items = [];
80
81 1
                foreach ($value as $index => $item) {
82 1
                    $items[$index] = $this->normalizeIfSupported($item, $format, $context);
83
                }
84
85 1
                $value = $items;
86
            }
87
88 5
            if (is_object($value)) {
89 3
                $value = $this->normalizeIfSupported($value, $format, $context);
90
            }
91
92 5
            $target = $binding ? ($binding->target ?? $binding->source ?? null) : $propertyMetadata->name;
93
94 5
            if (preg_match('/\./', $target)) {
95 2
                $path = implode("']['", explode('.', sprintf("['%s']", $target)));
96 2
                eval("\$data$path = \$value;");
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
97
            } else {
98 5
                $data[$target] = $value;
99
            }
100
        }
101
102 5
        $this->storage[$object] = $data;
103
104 5
        return $data;
105
    }
106
    
107 3
    private function normalizeIfSupported($value, string $format = null, array $context = [])
108
    {
109 3
        if (isset($this->normalizer)) {
110 1
            return $this->normalizer->normalize($value, $format, $context);
111
        }
112
113 2
        if ($this->supportsNormalization($value)) {
114 2
            return $this->normalize($value, $format, $context);
115
        }
116
        
117 1
        return $value;
118
    }
119
120 5
    public function supportsNormalization($data, $format = null): bool
121
    {
122 5
        return is_object($data) && !$data instanceof \DateTime;
123
    }
124
125 20
    public function setNormalizer(NormalizerInterface $normalizer)
126
    {
127 20
        $this->normalizer = $normalizer;
128 20
    }
129
}
130