Test Failed
Push — master ( 14a8e0...ef7d6f )
by Dominik
02:26
created

Normalizer::getLinksByLinkNormalizationMappings()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 7.456

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 4
cts 10
cp 0.4
rs 8.7972
c 0
b 0
f 0
cc 4
eloc 15
nc 4
nop 4
crap 7.456
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\NormalizationLinkMappingInterface;
9
use Chubbyphp\Serialization\Mapping\NormalizationObjectMappingInterface;
10
use Chubbyphp\Serialization\SerializerLogicException;
11
use Psr\Log\LoggerInterface;
12
use Psr\Log\NullLogger;
13
14
final class Normalizer implements NormalizerInterface
15
{
16
    /**
17
     * @var NormalizerObjectMappingRegistryInterface
18
     */
19
    private $normalizerObjectMappingRegistry;
20
21
    /**
22
     * @var LoggerInterface
23
     */
24
    private $logger;
25
26
    /**
27
     * @param NormalizerObjectMappingRegistryInterface $normalizerObjectMappingRegistry
28
     * @param LoggerInterface|null                     $logger
29
     */
30 4
    public function __construct(
31
        NormalizerObjectMappingRegistryInterface $normalizerObjectMappingRegistry,
32
        LoggerInterface $logger = null
33
    ) {
34 4
        $this->normalizerObjectMappingRegistry = $normalizerObjectMappingRegistry;
35 4
        $this->logger = $logger ?? new NullLogger();
36 4
    }
37
38
    /**
39
     * @param object                          $object
40
     * @param NormalizerContextInterface|null $context
41
     * @param string                          $path
42
     *
43
     * @return array
44
     */
45 4
    public function normalize($object, NormalizerContextInterface $context = null, string $path = ''): array
46
    {
47 4
        $this->validateDataType($object, $path);
48
49 3
        $context = $context ?? NormalizerContextBuilder::create()->getContext();
50
51 3
        $class = is_object($object) ? get_class($object) : $object;
52 3
        $objectMapping = $this->getObjectMapping($class);
53
54 2
        $fieldMappings = $objectMapping->getNormalizationFieldMappings($path);
55 2
        $fields = $this->getDataByFieldNormalizationMappings($context, $fieldMappings, $path, $object);
56
57 2
        $embeddedFieldMappings = $objectMapping->getNormalizationEmbeddedFieldMappings($path);
58 2
        $embeddedFields = $this->getDataByFieldNormalizationMappings($context, $embeddedFieldMappings, $path, $object);
59
60 2
        $linkMappings = $objectMapping->getNormalizationLinkMappings($path);
61 2
        $links = $this->getLinksByLinkNormalizationMappings($context, $linkMappings, $path, $object);
62
63 2
        $data = $fields;
64
65 2
        if ([] !== $embeddedFields) {
66 1
            $data['_embedded'] = $embeddedFields;
67
        }
68
69 2
        if ([] !== $links) {
70
            $data['_links'] = $links;
71
        }
72
73 2
        $data['_type'] = $objectMapping->getNormalizationType();
74
75 2
        return $data;
76
    }
77
78
    /**
79
     * @param object $object
80
     * @param string $path
81
     *
82
     * @throws SerializerLogicException
83
     */
84 4
    private function validateDataType($object, string $path)
85
    {
86 4
        if (!is_object($object)) {
87 1
            $exception = SerializerLogicException::createWrongDataType(gettype($object), $path);
88
89 1
            $this->logger->error('serialize: {exception}', ['exception' => $exception->getMessage()]);
90
91 1
            throw $exception;
92
        }
93 3
    }
94
95
    /**
96
     * @param string $class
97
     *
98
     * @return NormalizationObjectMappingInterface
99
     *
100
     * @throws SerializerLogicException
101
     */
102 3
    private function getObjectMapping(string $class): NormalizationObjectMappingInterface
103
    {
104
        try {
105 3
            return $this->normalizerObjectMappingRegistry->getObjectMapping($class);
106 1
        } catch (SerializerLogicException $exception) {
107 1
            $this->logger->error('serialize: {exception}', ['exception' => $exception->getMessage()]);
108
109 1
            throw $exception;
110
        }
111
    }
112
113
    /**
114
     * @param NormalizerContextInterface           $context
115
     * @param NormalizationFieldMappingInterface[] $normalizationFieldMappings
116
     * @param string                               $path
117
     * @param $object
118
     *
119
     * @return array
120
     */
121 2
    private function getDataByFieldNormalizationMappings(
122
        NormalizerContextInterface $context,
123
        array $normalizationFieldMappings,
124
        string $path,
125
        $object
126
    ): array {
127 2
        $data = [];
128 2
        foreach ($normalizationFieldMappings as $normalizationFieldMapping) {
129 2
            if (!$this->isWithinGroup($context, $normalizationFieldMapping)) {
130 1
                continue;
131
            }
132
133 2
            $fieldNormalizer = $normalizationFieldMapping->getFieldNormalizer();
134
135 2
            $name = $normalizationFieldMapping->getName();
136
137 2
            $subPath = $this->getSubPathByName($path, $name);
138
139 2
            $this->logger->info('serialize: path {path}', ['path' => $subPath]);
140
141 2
            $data[$name] = $fieldNormalizer->normalizeField($subPath, $object, $context, $this);
142
        }
143
144 2
        return $data;
145
    }
146
147
    /**
148
     * @param NormalizerContextInterface $context
149
     * @param NormalizationLinkMappingInterface[]                      $normalizationLinkMappings
150
     * @param string                     $path
151
     * @return array
152
     */
153 2
    private function getLinksByLinkNormalizationMappings(
154
        NormalizerContextInterface $context,
155
        array $normalizationLinkMappings,
156
        string $path,
157
        $object
158
    ): array {
159 2
        $links = [];
160 2
        foreach ($normalizationLinkMappings as $normalizationLinkMapping) {
161
            if (!$this->isWithinGroup($context, $normalizationLinkMapping)) {
162
                continue;
163
            }
164
165
            $linkNormalizer = $normalizationLinkMapping->getLinkNormalizer();
166
167
            if (null === $link = $linkNormalizer->normalizeLink($path, $object, $context)) {
168
                continue;
169
            }
170
171
            $links[$normalizationLinkMapping->getName()] = $link;
172
        }
173
174 2
        return $links;
175
    }
176
177
    /**
178
     * @param NormalizerContextInterface         $context
179
     * @param NormalizationFieldMappingInterface|NormalizationLinkMappingInterface $mapping
180
     *
181
     * @return bool
182
     */
183 2
    private function isWithinGroup(NormalizerContextInterface $context, $mapping): bool {
184 2
        if ([] === $groups = $context->getGroups()) {
185 1
            return true;
186
        }
187
188 1
        foreach ($mapping->getGroups() as $group) {
189 1
            if (in_array($group, $groups, true)) {
190 1
                return true;
191
            }
192
        }
193
194 1
        return false;
195
    }
196
197
    /**
198
     * @param string $path
199
     * @param string $name
200
     *
201
     * @return string
202
     */
203 2
    private function getSubPathByName(string $path, string $name): string
204
    {
205 2
        return '' === $path ? $name : $path.'.'.$name;
206
    }
207
}
208