Passed
Push — master ( 53dcee...da1c7b )
by Mike
05:24
created

ArrayHandler::validateWildcards()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 3
nop 3
dl 0
loc 15
ccs 8
cts 8
cp 1
crap 4
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Xervice\ArrayHandler\Business\Model;
5
6
7
use Xervice\ArrayHandler\Business\Model\ArrayLocator\ArrayLocatorInterface;
8
use Xervice\ArrayHandler\Dependency\FieldHandlerPluginInterface;
9
10
class ArrayHandler implements ArrayHandlerInterface
11
{
12
    /**
13
     * @var \Xervice\ArrayHandler\Dependency\FieldHandlerPluginInterface
14
     */
15
    private $fieldHandler;
16
17
    /**
18
     * @var \Xervice\ArrayHandler\Business\Model\ArrayLocator\ArrayLocatorInterface
19
     */
20
    private $arrayLocator;
21
22
    /**
23
     * ArrayHandler constructor.
24
     *
25
     * @param \Xervice\ArrayHandler\Dependency\FieldHandlerPluginInterface $fieldHandler
26
     * @param \Xervice\ArrayHandler\Business\Model\ArrayLocator\ArrayLocatorInterface $arrayLocator
27
     */
28 1
    public function __construct(
29
        FieldHandlerPluginInterface $fieldHandler,
30
        ArrayLocatorInterface $arrayLocator
31
    ) {
32 1
        $this->fieldHandler = $fieldHandler;
33 1
        $this->arrayLocator = $arrayLocator;
34 1
    }
35
36
    /**
37
     * @param array $payload
38
     * @param array $config
39
     *
40
     * @return array
41
     */
42 1
    public function handleArray(array $payload, array $config): array
43
    {
44 1
        $this->arrayLocator->init($payload);
45 1
        return $this->validateWithConfig($payload, $config);
46
    }
47
48
    /**
49
     * @param array $payload
50
     * @param array $config
51
     *
52
     * @return array
53
     */
54 1
    protected function validateWithConfig(array $payload, array $config): array
55
    {
56 1
        foreach ($config as $key => $configItem) {
57 1
            if (is_string($configItem)) {
58 1
                $payload = $this->validateField($payload, $configItem, $configItem);
59 1
            } elseif ($key === '*') {
60 1
                foreach ($payload as $dataKey => $subdata) {
61 1
                    $payload[$dataKey] = $this->handleArray($subdata, $configItem);
62
                }
63
            } else {
64 1
                $payload = $this->validateNested($payload, $configItem);
65
            }
66
        }
67
68 1
        return $payload;
69
    }
70
71
    /**
72
     * @param array $data
73
     * @param array $configs
74
     *
75
     * @return array
76
     */
77 1
    protected function validateNested(array $data, array $configs): array
78
    {
79 1
        foreach ($configs as $key => $fieldConfig) {
80 1
            $data = $this->validateByType($data, $key, $fieldConfig);
81
        }
82 1
        return $data;
83
    }
84
85
    /**
86
     * @param array $data
87
     * @param mixed $key
88
     * @param mixed $fieldConfig
89
     *
90
     * @return array
91
     */
92 1
    protected function validateByType(array $data, $key, $fieldConfig): array
93
    {
94 1
        if (is_string($fieldConfig)) {
95 1
            $key = $fieldConfig;
96
        }
97 1
        if (strpos($key, '.*') !== false) {
98 1
            $data = $this->validateWildcards($data, $key, $fieldConfig);
99 1
        } elseif (strpos($key, '.') !== false) {
100 1
            $data = $this->validateArrayKey($data, $key, $fieldConfig);
101
        } else {
102 1
            $data = $this->validateField($data, $key, $fieldConfig);
103
        }
104 1
        return $data;
105
    }
106
107
    /**
108
     * @param array $payload
109
     * @param string $key
110
     * @param mixed $config
111
     *
112
     * @return array
113
     */
114 1
    protected function validateWildcards(array $payload, string $key, $config): array
115
    {
116 1
        $keys = $this->arrayLocator->getKeysByPath($key);
117
118 1
        foreach ($keys as $ckey) {
119 1
            if (is_array($config)) {
120 1
                foreach ($config as $configItem) {
121 1
                    $payload = $this->validateArrayKey($payload, $ckey, $configItem);
122
                }
123
            } else {
124 1
                $payload = $this->validateArrayKey($payload, $ckey, $config);
125
            }
126
        }
127
128 1
        return $payload;
129
    }
130
131
    /**
132
     * @param array $data
133
     * @param string $key
134
     * @param mixed $fieldConfig
135
     *
136
     * @return array
137
     */
138 1
    protected function validateArrayKey(array $data, string $key, $fieldConfig): array
139
    {
140 1
        $keychain = explode('.', $key);
141 1
        $lastKey = $this->getLastArrayKey($keychain);
142
143 1
        $subdata = $this->getElementWithKey($data, $keychain);
144 1
        $subdata = $this->validateField($subdata, $keychain[$lastKey], $fieldConfig);
145
146 1
        return $this->setElementWithKey($data, $keychain, $subdata);
147
    }
148
149
    /**
150
     * @param array $data
151
     * @param array $keychain
152
     * @param $value
153
     *
154
     * @return array
155
     */
156 1
    private function setElementWithKey(array $data, array $keychain, $value): array
157
    {
158 1
        if (count($keychain) === 1) {
159 1
            return $value;
160
        }
161
162 1
        $key = array_shift($keychain);
163 1
        $data[$key] = $this->setElementWithKey($data[$key], $keychain, $value);
164
165 1
        return $data;
166
    }
167
168
    /**
169
     * @param array $data
170
     * @param array $keychain
171
     *
172
     * @return mixed
173
     */
174 1
    private function getElementWithKey(array $data, array $keychain)
175
    {
176 1
        if (count($keychain) === 1) {
177 1
            return $data;
178
        }
179
180 1
        $key = array_shift($keychain);
181 1
        return $this->getElementWithKey($data[$key], $keychain);
182
    }
183
184
    /**
185
     * @param array $array
186
     *
187
     * @return mixed
188
     */
189 1
    private function getLastArrayKey(array $array)
190
    {
191 1
        if (!function_exists("array_key_last")) {
192 1
            return array_keys($array)[count($array) - 1];
193
        }
194
195
        return array_key_last($array);
196
    }
197
198
    /**
199
     * @param array $data
200
     * @param string $fieldName
201
     * @param mixed $config
202
     *
203
     * @return array
204
     */
205 1
    protected function validateField(array $data, string $fieldName, $config): array
206
    {
207 1
        if (is_string($config)) {
208 1
            $data = $this->fieldHandler->handleSimpleConfig($data, $fieldName, $config);
209 1
        } elseif (is_array($config)) {
210 1
            $data = $this->fieldHandler->handleNestedConfig($data, $fieldName, $config);
211 1
        } elseif (is_callable($config)) {
212 1
            $data = $this->fieldHandler->handleCallableConfig($data, $fieldName, $config);
213
        }
214
215 1
        return $data;
216
    }
217
}