ObjectCollectionTransformer   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 169
Duplicated Lines 0 %

Test Coverage

Coverage 96.49%

Importance

Changes 0
Metric Value
eloc 48
dl 0
loc 169
ccs 55
cts 57
cp 0.9649
rs 10
c 0
b 0
f 0
wmc 23

10 Methods

Rating   Name   Duplication   Size   Complexity  
A isSequential() 0 3 1
A setMappingKeys() 0 3 1
A getMappingKeys() 0 3 1
A isArrayAndNotEmpty() 0 3 2
A transformArrayPartial() 0 14 2
A map() 0 15 2
A isDataSequential() 0 13 4
A transform() 0 19 4
A mappingKeysExist() 0 7 2
A supports() 0 9 4
1
<?php
2
3
namespace CCT\Component\Rest\Transformer\Response;
4
5
use CCT\Component\Rest\Http\ResponseInterface;
6
use CCT\Component\Rest\Serializer\ContextInterface;
7
use Symfony\Component\HttpFoundation\Response;
8
9
class ObjectCollectionTransformer extends AbstractSerializerResponseTransformer
10
{
11
    /**
12
     * @var array|null
13
     */
14
    protected $mappingKeys;
15
16
    /**
17
     * @param ResponseInterface|Response $response
18
     *
19
     * {@inheritdoc}
20
     */
21 3
    public function transform(ResponseInterface $response, ContextInterface $context = null): void
22
    {
23 3
        $data = $response->getData();
24
25 3
        if (!is_array($this->mappingKeys) || \count($this->mappingKeys) === 0) {
26 1
            $response->setData(
27 1
                $this->transformArrayPartial($data, $context)
28
            );
29 1
            return;
30
        }
31
32 2
        $mappedData = $this->map($response->getData());
33 2
        $transformedData = [];
34
35 2
        foreach ($mappedData as $key => $transformingData) {
36 2
            $transformedData[$key] = $this->transformArrayPartial($transformingData, $context);
37
        }
38
39 2
        $response->setData(array_merge($data, $transformedData));
40 2
    }
41
42
    /**
43
     * @param ResponseInterface|Response $response
44
     *
45
     * {@inheritdoc}
46
     */
47 8
    public function supports(ResponseInterface $response): bool
48
    {
49 8
        $data = $response->getData();
50
51
        return (
52 8
            $response->isSuccessful()
53 8
            && $this->isArrayAndNotEmpty($data)
54 8
            && $this->mappingKeysExist($data)
55 8
            && $this->isDataSequential($this->map($data))
56
        );
57
    }
58
59
    /**
60
     * @param array $transformingData
61
     * @param ContextInterface $context
62
     *
63
     * @return array
64
     */
65 3
    protected function transformArrayPartial(array $transformingData, ContextInterface $context = null): array
66
    {
67 3
        $transformedData = [];
68
69 3
        foreach ($transformingData as $key => $object) {
70 3
            $transformedData[$key] = $this->serializer->deserialize(
71 3
                json_encode($object),
72 3
                $this->class,
73 3
                'json',
74 3
                $context ?? $this->context
75
            );
76
        }
77
78 3
        return $transformedData;
79
    }
80
81
    /**
82
     * Check if $data is an array and not empty
83
     *
84
     * @param mixed $data
85
     *
86
     * @return bool
87
     */
88 7
    protected function isArrayAndNotEmpty($data): bool
89
    {
90 7
        return \is_array($data) && !empty($data);
91
    }
92
93
    /**
94
     * Extract collection from response array based on mapping key.
95
     * Supports single level only
96
     * If no mapping key returns full data
97
     *
98
     * @param $data
99
     *
100
     * @return array
101
     */
102 5
    protected function map(array $data): array
103
    {
104 5
        if (null === $this->mappingKeys) {
105 2
            return $data;
106
        }
107
108 3
        $mappingKeys = $this->mappingKeys;
109
110
        return
111 3
            array_filter(
112 3
                $data,
113 3
                function ($key) use ($mappingKeys) {
114 3
                    return \in_array($key, $mappingKeys, true);
115 3
                },
116 3
                ARRAY_FILTER_USE_KEY
117
            );
118
    }
119
120
    /**
121
     * @param array $data
122
     *
123
     * @return bool
124
     */
125 4
    protected function mappingKeysExist(array $data): bool
126
    {
127 4
        if (null === $this->mappingKeys) {
128 2
            return true;
129
        }
130
131 2
        return (bool)\count(array_intersect($this->mappingKeys, array_keys($data))) > 0;
132
    }
133
134
    /**
135
     * @return array|null
136
     */
137
    public function getMappingKeys(): ?array
138
    {
139
        return $this->mappingKeys;
140
    }
141
142
    /**
143
     * @param null|array $mappingKeys
144
     */
145 4
    public function setMappingKeys(array $mappingKeys = null): void
146
    {
147 4
        $this->mappingKeys = $mappingKeys;
148 4
    }
149
150
    /**
151
     * @param array $data
152
     *
153
     * @return bool
154
     */
155 3
    protected function isDataSequential(array $data): bool
156
    {
157 3
        if (null === $this->mappingKeys) {
158 2
            return $this->isSequential($data);
159
        }
160
161 1
        foreach ($data as $sequentialArray) {
162 1
            if (false === $this->isSequential($sequentialArray)) {
163 1
                return false;
164
            }
165
        }
166
167 1
        return true;
168
    }
169
170
    /**
171
     * @param array $data
172
     *
173
     * @return bool
174
     */
175 3
    protected function isSequential(array $data): bool
176
    {
177 3
        return array_keys($data) === range(0, \count($data) - 1);
178
    }
179
}
180