Test Failed
Push — master ( 8e0c78...7b15c4 )
by Dominik
01:51
created

Normalizer   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 166
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 7.69%

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 10
dl 0
loc 166
ccs 4
cts 52
cp 0.0769
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
B normalize() 0 31 4
A validateDataType() 0 10 2
A getObjectMapping() 0 10 2
B getDataByFieldNormalizationMappings() 0 25 3
A isWithinGroup() 0 16 4
A getSubPathByName() 0 4 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chubbyphp\Serialization\Normalizer;
6
7
use Chubbyphp\Serialization\Mapping\NormalizationFieldMappingInterface;
8
use Chubbyphp\Serialization\Mapping\NormalizationObjectMappingInterface;
9
use Chubbyphp\Serialization\SerializerLogicException;
10
use Psr\Log\LoggerInterface;
11
use Psr\Log\NullLogger;
12
13
final class Normalizer implements NormalizerInterface
14
{
15
    /**
16
     * @var NormalizerObjectMappingRegistryInterface
17
     */
18
    private $normalizerObjectMappingRegistry;
19
20
    /**
21
     * @var LoggerInterface
22
     */
23
    private $logger;
24
25
    /**
26
     * @param NormalizerObjectMappingRegistryInterface $normalizerObjectMappingRegistry
27
     * @param LoggerInterface|null                     $logger
28
     */
29 1
    public function __construct(
30
        NormalizerObjectMappingRegistryInterface $normalizerObjectMappingRegistry,
31
        LoggerInterface $logger = null
32
    ) {
33 1
        $this->normalizerObjectMappingRegistry = $normalizerObjectMappingRegistry;
34 1
        $this->logger = $logger ?? new NullLogger();
35 1
    }
36
37
    /**
38
     * @param object                          $object
39
     * @param NormalizerContextInterface|null $context
40
     * @param string                          $path
41
     *
42
     * @return array
43
     */
44
    public function normalize($object, NormalizerContextInterface $context = null, string $path = ''): array
45
    {
46
        $this->validateDataType($object, $path);
47
48
        $context = $context ?? NormalizerContextBuilder::create()->getContext();
49
50
        $class = is_object($object) ? get_class($object) : $object;
51
        $objectMapping = $this->getObjectMapping($class);
52
53
        $fieldMappings = $objectMapping->getNormalizationFieldMappings($path);
54
        $fields = $this->getDataByFieldNormalizationMappings($context, $fieldMappings, $path, $object);
55
56
        $embeddedFieldMappings = $objectMapping->getNormalizationEmbeddedFieldMappings($path);
57
        $embeddedFields = $this->getDataByFieldNormalizationMappings($context, $embeddedFieldMappings, $path, $object);
58
59
        $links = [];
60
61
        $data = $fields;
62
63
        if ([] !== $embeddedFields) {
64
            $data['_embedded'] = $embeddedFields;
65
        }
66
67
        if ([] !== $links) {
68
            $data['_links'] = $links;
69
        }
70
71
        $data['_type'] = $objectMapping->getNormalizationType();
72
73
        return $data;
74
    }
75
76
    /**
77
     * @param object $object
78
     * @param string $path
79
     *
80
     * @throws SerializerLogicException
81
     */
82
    private function validateDataType($object, string $path)
83
    {
84
        if (!is_object($object)) {
85
            $exception = SerializerLogicException::createWrongDataType(gettype($object), $path);
86
87
            $this->logger->error('serialize: {exception}', ['exception' => $exception->getMessage()]);
88
89
            throw $exception;
90
        }
91
    }
92
93
    /**
94
     * @param string $class
95
     *
96
     * @return NormalizationObjectMappingInterface
97
     *
98
     * @throws SerializerLogicException
99
     */
100
    private function getObjectMapping(string $class): NormalizationObjectMappingInterface
101
    {
102
        try {
103
            return $this->normalizerObjectMappingRegistry->getObjectMapping($class);
104
        } catch (SerializerLogicException $exception) {
105
            $this->logger->error('serialize: {exception}', ['exception' => $exception->getMessage()]);
106
107
            throw $exception;
108
        }
109
    }
110
111
    /**
112
     * @param NormalizerContextInterface           $context
113
     * @param NormalizationFieldMappingInterface[] $normalizationFieldMappings
114
     * @param string                               $path
115
     * @param $object
116
     *
117
     * @return array
118
     */
119
    private function getDataByFieldNormalizationMappings(
120
        NormalizerContextInterface $context,
121
        array $normalizationFieldMappings,
122
        string $path,
123
        $object
124
    ): array {
125
        $data = [];
126
        foreach ($normalizationFieldMappings as $normalizationFieldMapping) {
127
            $fieldNormalizer = $normalizationFieldMapping->getFieldNormalizer();
128
129
            if (!$this->isWithinGroup($context, $normalizationFieldMapping)) {
130
                continue;
131
            }
132
133
            $name = $normalizationFieldMapping->getName();
134
135
            $subPath = $this->getSubPathByName($path, $name);
136
137
            $this->logger->info('serialize: path {path}', ['path' => $subPath]);
138
139
            $data[$name] = $fieldNormalizer->normalizeField($subPath, $object, $context, $this);
140
        }
141
142
        return $data;
143
    }
144
145
    /**
146
     * @param NormalizerContextInterface         $context
147
     * @param NormalizationFieldMappingInterface $fieldMapping
148
     *
149
     * @return bool
150
     */
151
    private function isWithinGroup(
152
        NormalizerContextInterface $context,
153
        NormalizationFieldMappingInterface $fieldMapping
154
    ): bool {
155
        if ([] === $groups = $context->getGroups()) {
156
            return true;
157
        }
158
159
        foreach ($fieldMapping->getGroups() as $group) {
160
            if (in_array($group, $groups, true)) {
161
                return true;
162
            }
163
        }
164
165
        return false;
166
    }
167
168
    /**
169
     * @param string $path
170
     * @param string $name
171
     *
172
     * @return string
173
     */
174
    private function getSubPathByName(string $path, string $name): string
175
    {
176
        return '' === $path ? $name : $path.'.'.$name;
177
    }
178
}
179