Test Failed
Push — master ( 1f8fc2...506f14 )
by Dominik
02:22
created

Normalizer::getLinksByLinkNormalizationMappings()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3.7085

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 4
cts 7
cp 0.5714
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 12
nc 3
nop 4
crap 3.7085
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
            $fieldNormalizer = $normalizationFieldMapping->getFieldNormalizer();
130
131 2
            if (!$this->isWithinGroup($context, $normalizationFieldMapping)) {
132 1
                continue;
133
            }
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[]                      $linkMappings
150
     * @param string                     $path
151
     * @return array
152
     */
153 2
    private function getLinksByLinkNormalizationMappings(
154
        NormalizerContextInterface $context,
155
        array $linkMappings,
156
        string $path,
157
        $object
158
    ): array {
159 2
        $links = [];
160 2
        foreach ($linkMappings as $linkMapping) {
161
            if (null !== $link = $linkMapping->getLinkNormalizer()->normalizeLink($path, $object, $context)) {
162
                continue;
163
            }
164
165
            $links[$linkMapping->getName()] = $link;
166
        }
167
168 2
        return $links;
169
    }
170
171
    /**
172
     * @param NormalizerContextInterface         $context
173
     * @param NormalizationFieldMappingInterface $fieldMapping
174
     *
175
     * @return bool
176
     */
177 2
    private function isWithinGroup(
178
        NormalizerContextInterface $context,
179
        NormalizationFieldMappingInterface $fieldMapping
180
    ): bool {
181 2
        if ([] === $groups = $context->getGroups()) {
182 1
            return true;
183
        }
184
185 1
        foreach ($fieldMapping->getGroups() as $group) {
186 1
            if (in_array($group, $groups, true)) {
187 1
                return true;
188
            }
189
        }
190
191 1
        return false;
192
    }
193
194
    /**
195
     * @param string $path
196
     * @param string $name
197
     *
198
     * @return string
199
     */
200 2
    private function getSubPathByName(string $path, string $name): string
201
    {
202 2
        return '' === $path ? $name : $path.'.'.$name;
203
    }
204
}
205