Passed
Push — master ( 13fc71...0b75e6 )
by Mike
02:03
created

ArrayHandler::getElementWithKey()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

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