ArrayRemapper   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 103
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 57
c 1
b 0
f 0
dl 0
loc 103
rs 10
wmc 21

7 Methods

Rating   Name   Duplication   Size   Complexity  
A toReplacement() 0 11 1
A reverseRemap() 0 18 4
A set() 0 11 3
A visit() 0 16 5
A flattenArray() 0 8 3
A remap() 0 18 4
A toRegex() 0 3 1
1
<?php
2
3
namespace W2w\Laravel\Apie\Plugins\Illuminate\Eloquent;
4
5
use Generator;
6
7
class ArrayRemapper
8
{
9
    public static function remap(array $mapping, array $input): array
10
    {
11
        $staticMapping = [];
12
        $dynamicMapping = [];
13
        foreach (self::flattenArray($mapping) as $key => $value) {
14
            if (strpos($key, '*') !== false) {
15
                $dynamicMapping[self::toRegex($key)] = self::toReplacement($value);
16
            } else {
17
                $staticMapping[$key] = $value;
18
            }
19
        }
20
        $result = [];
21
22
        foreach (self::visit($input, $staticMapping, $dynamicMapping) as $key => $value) {
23
            $keys = explode('.', $key);
24
            self::set($result, $keys, $value);
25
        }
26
        return $result;
27
    }
28
29
    public static function reverseRemap(array $mapping, array $input): array
30
    {
31
        $staticMapping = [];
32
        $dynamicMapping = [];
33
        foreach (self::flattenArray($mapping) as $value => $key) {
34
            if (strpos($key, '*') !== false) {
35
                $dynamicMapping[self::toRegex($key)] = self::toReplacement($value);
36
            } else {
37
                $staticMapping[$key] = $value;
38
            }
39
        }
40
        $result = [];
41
42
        foreach (self::visit($input, $staticMapping, $dynamicMapping) as $key => $value) {
43
            $keys = explode('.', $key);
44
            self::set($result, $keys, $value);
45
        }
46
        return $result;
47
    }
48
49
    private static function set(array& $input, array $keys, $value) {
50
        $ptr = &$input;
51
        while (count($keys) > 1) {
52
            $key = array_shift($keys);
53
            if (!array_key_exists($key, $ptr)) {
54
                $ptr[$key] = [];
55
            }
56
            $ptr = &$ptr[$key];
57
        }
58
        $key = array_shift($keys);
59
        $ptr[$key] = $value;
60
    }
61
62
    private static function flattenArray(array $input, string $prefixKey = ''): Generator
63
    {
64
        foreach ($input as $key => $value) {
65
            if (is_array($value)) {
66
                yield from self::flattenArray($value, $prefixKey . '.' . $key);
67
                continue;
68
            }
69
            yield ltrim($prefixKey . '.' . $key, '.') => $value;
70
        }
71
    }
72
73
    private static function visit(array& $input, array $staticMapping, array $dynamicMapping): Generator
74
    {
75
76
        $input = iterator_to_array(self::flattenArray($input));
77
78
79
        foreach ($input as $key => $value) {
80
            if (isset($staticMapping[$key])) {
81
                yield $staticMapping[$key] => $value;
82
                continue;
83
            }
84
            foreach ($dynamicMapping as $regex => $result) {
85
                if (preg_match($regex, $key)) {
86
                    $calculatedKey = preg_replace($regex, $result, $key);
87
                    yield $calculatedKey => $value;
88
                    break;
89
                }
90
            }
91
        }
92
    }
93
94
    private static function toRegex(string $input): string
95
    {
96
        return '/^' . str_replace('\\*', '([a-zA-Z0-9_-]+)', preg_quote($input, '/')) . '$/';
97
    }
98
99
    private static function toReplacement(string $input): string
100
    {
101
        $counter = 1;
102
        return preg_replace_callback(
103
                '/' . preg_quote('*', '/') . '/',
104
                function () use (&$counter) {
105
                    $res = '${' . $counter . '}';
106
                    $counter++;
107
                    return $res;
108
                },
109
                $input
110
            );
111
    }
112
}
113