Passed
Push — master ( acd513...675cc6 )
by Andrea Marco
02:53 queued 11s
created

ArrayConverter::formatArrayKey()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
3
namespace Cerbero\Dto\Manipulators;
4
5
/**
6
 * The array converter.
7
 *
8
 */
9
class ArrayConverter
10
{
11
    /**
12
     * The snake case pattern
13
     *
14
     * - Look behind for lower case letters or digits
15
     * - Look ahead for upper case letters
16
     */
17
    public const RE_SNAKE_CASE = '/(?<=[a-z\d])(?=[A-Z])/';
18
19
    /**
20
     * The class instance.
21
     *
22
     * @var self
23
     */
24
    protected static $instance;
25
26
    /**
27
     * The registered conversions.
28
     *
29
     * @var array
30
     */
31
    protected $conversions = [];
32
33
    /**
34
     * The cached value converters.
35
     *
36
     * @var ValueConverter[]
37
     */
38
    protected $cachedConverters = [];
39
40
    /**
41
     * Instantiate the class
42
     *
43
     */
44 15
    protected function __construct()
45
    {
46
        //
47 15
    }
48
49
    /**
50
     * Retrieve the class instance
51
     *
52
     * @return self
53
     */
54 120
    public static function instance(): self
55
    {
56 120
        return static::$instance = static::$instance ?: new static();
57
    }
58
59
    /**
60
     * Set the given value conversions
61
     *
62
     * @param array $conversions
63
     * @return self
64
     */
65 15
    public function setConversions(array $conversions): self
66
    {
67 15
        $this->conversions = $conversions;
68
69 15
        return $this;
70
    }
71
72
    /**
73
     * Retrieve the value conversions
74
     *
75
     * @return array
76
     */
77 24
    public function getConversions(): array
78
    {
79 24
        return $this->conversions;
80
    }
81
82
    /**
83
     * Convert the given item into an array
84
     *
85
     * @param mixed $item
86
     * @param bool $snakeCase
87
     * @return mixed
88
     */
89 57
    public function convert($item, $snakeCase = false)
90
    {
91 57
        if (is_object($item) && $converter = $this->getConverterByInstance($item)) {
92 3
            return $converter->fromDto($item);
93
        }
94
95 57
        if (is_iterable($item)) {
96 24
            $result = [];
97
98 24
            foreach ($item as $key => $value) {
99 24
                $formattedKey = $this->formatArrayKey($key, $snakeCase);
100 24
                $result[$formattedKey] = $this->convert($value);
101
            }
102
103 24
            return $result;
104
        }
105
106 57
        return $item;
107
    }
108
109
    /**
110
     * Retrieve the converter for the given object instance
111
     *
112
     * @param object $instance
113
     * @return ValueConverter|null
114
     */
115 21
    public function getConverterByInstance($instance): ?ValueConverter
116
    {
117 21
        $class = get_class($instance);
118
119 21
        if (isset($this->cachedConverters[$class])) {
120 3
            return $this->cachedConverters[$class];
121
        }
122
123 21
        foreach ($this->getConversions() as $type => $class) {
124 21
            if (is_a($instance, $type)) {
125 6
                $converter = $this->resolveConverter($class);
126 11
                return $this->cachedConverters[$class] = $this->cachedConverters[$type] = $converter;
127
            }
128
        }
129
130 18
        return null;
131
    }
132
133
    /**
134
     * Retrieve the instance of the given converter
135
     *
136
     * @param string $converter
137
     * @return ValueConverter
138
     */
139 9
    protected function resolveConverter(string $converter): ValueConverter
140
    {
141 9
        return new $converter();
142
    }
143
144
    /**
145
     * Retrieve the formatted array key
146
     *
147
     * @param string $key
148
     * @param bool $snakeCase
149
     * @return string
150
     */
151 24
    protected function formatArrayKey(string $key, bool $snakeCase): string
152
    {
153 24
        if (!$snakeCase) {
154 24
            return $key;
155
        }
156
157 3
        return strtolower(preg_replace(static::RE_SNAKE_CASE, '_', $key));
158
    }
159
160
    /**
161
     * Retrieve the converter for the given class
162
     *
163
     * @param string $class
164
     * @return ValueConverter|null
165
     */
166 84
    public function getConverterByClass(string $class): ?ValueConverter
167
    {
168 84
        if (isset($this->cachedConverters[$class])) {
169 6
            return $this->cachedConverters[$class];
170
        }
171
172 81
        if ($converter = $this->conversions[$class] ?? null) {
173 3
            return $this->cachedConverters[$class] = $this->resolveConverter($converter);
174
        }
175
176 81
        return null;
177
    }
178
}
179