Completed
Push — master ( d7f465...3873b4 )
by Dmitry
04:58
created

Schema::formatValue()   C

Complexity

Conditions 13
Paths 13

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 6.6166
c 0
b 0
f 0
cc 13
nc 13
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Tarantool\Mapper;
6
7
use Closure;
8
use Exception;
9
use Tarantool\Client\Schema\Criteria;
10
use Tarantool\Client\Schema\Space as ClientSpace;
11
12
class Schema
13
{
14
    private $mapper;
15
16
    private $names = [];
17
    private $spaces = [];
18
    private $params = [];
19
    private $engines = [];
20
21
    public function __construct(Mapper $mapper, $meta = null)
22
    {
23
        $this->mapper = $mapper;
24
        if ($meta) {
25
            $this->setMeta($meta);
26
        } else {
27
            $this->reset();
28
        }
29
    }
30
31
    public function createSpace(string $space, array $config = []): Space
32
    {
33
        $options = [
34
            'engine' => 'memtx',
35
        ];
36
37
        foreach (['engine', 'is_local', 'temporary', 'is_sync', 'if_not_exists'] as $key) {
38
            if (array_key_exists($key, $config)) {
39
                $options[$key] = $config[$key];
40
            }
41
        }
42
43
        if (!in_array($options['engine'], ['memtx', 'vinyl'])) {
44
            throw new Exception("Invalid engine " . $options['engine']);
45
        }
46
47
        [$id] = $this->mapper->getClient()->evaluate("
0 ignored issues
show
Bug introduced by
The variable $id does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
48
            local space, options = ...
49
            box.schema.space.create(space, options)
50
            return box.space[space].id
51
        ", $space, $options);
52
53
        $this->names[$space] = $id;
54
        $this->engines[$space] = $options['engine'];
55
56
        $this->spaces[$id] = new Space($this->mapper, $id, $space, $options['engine']);
57
58
        $properties = array_key_exists('properties', $config) ? $config['properties'] : $config;
59
60
        if ($properties) {
61
            $this->spaces[$id]->addProperties($properties);
62
        }
63
64
        return $this->spaces[$id];
65
    }
66
67
    public function dropSpace(string $space)
68
    {
69
        if (!$this->hasSpace($space)) {
70
            throw new Exception("No space $space");
71
        }
72
73
        $this->mapper->getClient()->evaluate(sprintf("box.space.%s:drop()", $space));
74
75
        unset($this->spaces[$this->names[$space]], $this->engines[$space], $this->names[$space]);
76
    }
77
78
    public function getDefaultValue(string $type)
79
    {
80
        switch (strtolower($type)) {
81
            case 'str':
82
            case 'string':
83
                return (string) null;
84
85
            case 'bool':
86
            case 'boolean':
87
                return (bool) null;
88
89
            case 'double':
90
            case 'float':
91
            case 'number':
92
                return (float) null;
93
94
            case 'integer':
95
            case 'unsigned':
96
            case 'num':
97
            case 'NUM':
98
                return (int) null;
99
        }
100
        throw new Exception("Invalid type $type");
101
    }
102
103
    public function formatValue(string $type, $value)
104
    {
105
        if ($value === null) {
106
            return null;
107
        }
108
        switch (strtolower($type)) {
109
            case 'str':
110
            case 'string':
111
                return (string) $value;
112
113
            case 'double':
114
            case 'float':
115
            case 'number':
116
                return (float) $value;
117
118
            case 'bool':
119
            case 'boolean':
120
                return (bool) $value;
121
122
            case 'integer':
123
            case 'unsigned':
124
            case 'num':
125
            case 'NUM':
126
                return (int) $value;
127
128
            default:
129
                return $value;
130
        }
131
    }
132
133
    public function getSpace($id): Space
134
    {
135
        if (is_string($id)) {
136
            return $this->getSpace($this->getSpaceId($id));
137
        }
138
139
        if (!$id) {
140
            throw new Exception("Space id or name not defined");
141
        }
142
143
        if (!array_key_exists($id, $this->spaces)) {
144
            $name = array_search($id, $this->names);
145
            $meta = array_key_exists($id, $this->params) ? $this->params[$id] : null;
146
            $engine = $this->engines[$name];
147
            $this->spaces[$id] = new Space($this->mapper, $id, $name, $engine, $meta);
148
        }
149
        return $this->spaces[$id];
150
    }
151
152
    public function getSpaceId(string $name): int
153
    {
154
        if (!$this->hasSpace($name)) {
155
            throw new Exception("No space $name");
156
        }
157
        return $this->names[$name];
158
    }
159
160
    public function getSpaces(): array
161
    {
162
        foreach ($this->names as $id) {
163
            $this->getSpace($id);
164
        }
165
        return $this->spaces;
166
    }
167
168
    public function hasSpace(string $name): bool
169
    {
170
        return array_key_exists($name, $this->names);
171
    }
172
173
    public function once(string $name, Closure $callback)
174
    {
175
        $key = 'mapper-once' . $name;
176
        $row = $this->mapper->findOne('_schema', ['key' => $key]);
177
        if (!$row) {
178
            $this->mapper->create('_schema', ['key' => $key]);
179
            return $callback($this->mapper);
180
        }
181
    }
182
183
    public function forgetOnce(string $name)
184
    {
185
        $key = 'mapper-once' . $name;
186
        $row = $this->mapper->findOne('_schema', ['key' => $key]);
187
        if ($row) {
188
            $this->mapper->remove($row);
189
            return true;
190
        }
191
192
        return false;
193
    }
194
195
    public function reset(): self
196
    {
197
        $this->names = [];
198
        $this->engines = [];
199
    
200
        $data = $this->mapper->getClient()->getSpace('_vspace')->select(Criteria::allIterator());
201
        foreach ($data as $tuple) {
202
            $this->names[$tuple[2]] = $tuple[0];
203
            $this->engines[$tuple[2]] = $tuple[3];
204
        }
205
206
        foreach ($this->getSpaces() as $space) {
207
            if (!array_key_exists($space->getName(), $this->names)) {
208
                unset($this->spaces[$space->getId()]);
209
            }
210
        }
211
212
        return $this;
213
    }
214
215
    public function getMeta(): array
216
    {
217
        $params = [];
218
        foreach ($this->getSpaces() as $space) {
219
            $params[$space->getId()] = $space->getMeta();
220
        }
221
222
        return [
223
            'engines' => $this->engines,
224
            'names' => $this->names,
225
            'params' => $params,
226
        ];
227
    }
228
229
    public function setMeta($meta): self
230
    {
231
        $this->engines = $meta['engines'];
232
        $this->names = $meta['names'];
233
        $this->params = $meta['params'];
234
235
        return $this;
236
    }
237
238
    private $underscores = [];
239
240
    public function toUnderscore(string $input): string
241
    {
242
        if (!array_key_exists($input, $this->underscores)) {
243
            preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
244
            $ret = $matches[0];
245
            foreach ($ret as &$match) {
246
                $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
247
            }
248
            $this->underscores[$input] = implode('_', $ret);
249
        }
250
        return $this->underscores[$input];
251
    }
252
253
    private $camelcase = [];
254
255
    public function toCamelCase(string $input): string
256
    {
257
        if (!array_key_exists($input, $this->camelcase)) {
258
            $this->camelcase[$input] = lcfirst(implode('', array_map('ucfirst', explode('_', $input))));
259
        }
260
        return $this->camelcase[$input];
261
    }
262
}
263