Completed
Push — master ( c0ae32...7019ae )
by JHONATAN
02:56
created

Normalizer::supportsNormalization()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 2
eloc 1
nc 2
nop 2
crap 2
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 26
    public function __construct(MetadataFactoryInterface $metadataFactory)
37
    {
38 26
        $this->metadataFactory = $metadataFactory;
39 26
        $this->clear();
40 26
    }
41
    
42 7
    public function normalize($object, $format = null, array $context = [])
43
    {
44 7
        if ($this->storage->offsetExists($object)) {
45
            return $this->storage[$object];
46
        }
47
48 7
        $data = $this->extractData($object, $format, $context);
49
50 7
        return $data;
51
    }
52
53 7
    private function extractData($object, string $format = null, array $context = []): array
54
    {
55 7
        $objectMetadata = $this->metadataFactory->getMetadataForClass(get_class($object));
56
57 7
        if (!$objectMetadata instanceof ClassMetadata) {
58
            throw new RuntimeException('invalid metadata class');
59
        }
60
61 7
        $data = [];
62
63 7
        if ($objectMetadata->reflection->getParentClass()) {
64
            $data['type'] = get_class($object);
65
        }
66
67
        /* @var $propertyMetadata PropertyMetadata */
68 7
        foreach ($objectMetadata->propertyMetadata as $propertyMetadata) {
69 7
            $binding = $propertyMetadata->getAnnotation(Bindings::class);
70 7
            $value   = $propertyMetadata->getValue($object);
71
72 7
            if ($propertyMetadata->hasAnnotation(Exclude::class)
73 7
                && $propertyMetadata->getAnnotation(Exclude::class)->output) {
74
                continue;
75
            }
76
77 7
            if ((is_array($value) || $value instanceof \Traversable)
78 7
                && (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 7
            if (is_object($value)) {
89 4
                $value = $this->normalizeIfSupported($value, $format, $context);
90
            }
91
92 7
            $target = $binding
93 5
                ? ($binding->target ?? $binding->source ?? $propertyMetadata->name)
94 7
                : $propertyMetadata->name;
95
96 7
            if (preg_match('/\./', $target)) {
97 2
                $path = implode("']['", explode('.', sprintf("['%s']", $target)));
98 2
                eval("\$data$path = \$value;");
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
99
            } else {
100 7
                $data[$target] = $value;
101
            }
102
        }
103
104 7
        $this->storage[$object] = $data;
105
106 7
        return $data;
107
    }
108
    
109 4
    private function normalizeIfSupported($value, string $format = null, array $context = [])
110
    {
111 4
        if (isset($this->normalizer)) {
112 2
            return $this->normalizer->normalize($value, $format, $context);
113
        }
114
115 2
        if ($this->supportsNormalization($value)) {
116 2
            return $this->normalize($value, $format, $context);
117
        }
118
        
119 1
        return $value;
120
    }
121
122 7
    public function supportsNormalization($data, $format = null): bool
123
    {
124 7
        return is_object($data) && !$data instanceof \DateTime;
125
    }
126
127 24
    public function setNormalizer(NormalizerInterface $normalizer)
128
    {
129 24
        $this->normalizer = $normalizer;
130 24
    }
131
132 26
    public function clear()
133
    {
134 26
        $this->storage = new \SplObjectStorage();
135 26
    }
136
}
137