Completed
Push — master ( 43d7fb...779a1c )
by Dmitry
03:34
created

Schema::getSpaceId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
1
<?php
2
3
namespace Tarantool\Mapper;
4
5
use Exception;
6
7
class Schema
8
{
9
    private $mapper;
10
11
    private $names = [];
12
    private $spaces = [];
13
    private $params = [];
14
15
    public function __construct(Mapper $mapper, $meta = null)
16
    {
17
        $this->mapper = $mapper;
18
        if ($meta) {
19
            $this->setMeta($meta);
20
        } else {
21
            $this->reset();
22
        }
23
    }
24
25
    public function createSpace($space, $config = [])
26
    {
27
        $engine = 'memtx';
28
        if (array_key_exists('properties', $config)) {
29
            if (array_key_exists('engine', $config)) {
30
                $engine = $config['engine'];
31
                if (!in_array($engine, ['memtx', 'vinyl'])) {
32
                    throw new Exception("Invalid engine $engine");
33
                }
34
            }
35
        }
36
37
        $id = $this->mapper->getClient()->evaluate("
38
            box.schema.space.create('$space', {
39
                engine = '$engine'
40
            })
41
            return box.space.$space.id
42
        ")->getData()[0];
43
44
        $this->names[$space] = $id;
45
        $this->engines[$space] = $engine;
0 ignored issues
show
Bug introduced by
The property engines does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
46
47
        $this->spaces[$id] = new Space($this->mapper, $id, $space, $engine);
48
49
        $properties = array_key_exists('properties', $config) ? $config['properties'] : $config;
50
51
        if ($properties) {
52
            $this->spaces[$id]->addProperties($properties);
53
        }
54
55
        return $this->spaces[$id];
56
    }
57
58
    public function getDefaultValue($type)
59
    {
60
        switch ($type) {
61
            case 'STR':
62
            case 'STRING':
63
            case 'str':
64
            case 'string':
65
                return (string) null;
66
67
            case 'double':
68
            case 'float':
69
            case 'number':
70
                return (float) null;
71
72
            case 'unsigned':
73
            case 'UNSIGNED':
74
            case 'num':
75
            case 'NUM':
76
                return (int) null;
77
        }
78
        throw new Exception("Invalid type $type");
79
    }
80
81
    public function formatValue($type, $value)
82
    {
83
        if (is_null($value)) {
84
            return null;
85
        }
86
        switch ($type) {
87
            case 'STR':
88
            case 'STRING':
89
            case 'str':
90
            case 'string':
91
                return (string) $value;
92
93
            case 'double':
94
            case 'float':
95
            case 'number':
96
                return (float) $value;
97
98
            case 'unsigned':
99
            case 'UNSIGNED':
100
            case 'num':
101
            case 'NUM':
102
                return (int) $value;
103
104
            default:
105
                return $value;
106
        }
107
    }
108
109
    public function getSpace($id)
110
    {
111
        if (is_string($id)) {
112
            return $this->getSpace($this->getSpaceId($id));
113
        }
114
115
        if (!$id) {
116
            throw new Exception("Space id or name not defined");
117
        }
118
119
        if (!array_key_exists($id, $this->spaces)) {
120
            $name = array_search($id, $this->names);
121
            $meta = array_key_exists($id, $this->params) ? $this->params[$id] : null;
122
            $engine = $this->engines[$name];
123
            $this->spaces[$id] = new Space($this->mapper, $id, $name, $engine, $meta);
124
        }
125
        return $this->spaces[$id];
126
    }
127
128
    public function getSpaceId($name)
129
    {
130
        if (!$this->hasSpace($name)) {
131
            throw new Exception("No space $name");
132
        }
133
        return $this->names[$name];
134
    }
135
136
    public function getSpaces()
137
    {
138
        foreach ($this->names as $id) {
139
            $this->getSpace($id);
140
        }
141
        return $this->spaces;
142
    }
143
144
    public function hasSpace($name)
145
    {
146
        return array_key_exists($name, $this->names);
147
    }
148
149
    public function once($name, $callback)
150
    {
151
        $key = 'mapper-once' . $name;
152
153
        $rows = $this->mapper->find('_schema', ['key' => $key]);
154
        if (!count($rows)) {
155
            $this->mapper->create('_schema', ['key' => $key]);
156
            return $callback($this->mapper);
157
        }
158
    }
159
160
    public function reset()
161
    {
162
        [$this->names, $this->engines] = $this->mapper->getClient()->evaluate("
163
            local spaces = {}
164
            local engines = {}
165
            local i, s
166
            for i, s in box.space._vspace:pairs() do
167
                spaces[s[3]] = s[1]
168
                engines[s[3]] = s[4]
169
            end
170
            return spaces, engines
171
        ")->getData();
172
    }
173
174
    public function getMeta()
175
    {
176
        $params = [];
177
        foreach ($this->getSpaces() as $space) {
178
            $params[$space->getId()] = $space->getMeta();
179
        }
180
181
        return [
182
            'engines' => $this->engines,
183
            'names' => $this->names,
184
            'params' => $params,
185
        ];
186
    }
187
188
    public function setMeta($meta)
189
    {
190
        $this->engines = $meta['engines'];
191
        $this->names = $meta['names'];
192
        $this->params = $meta['params'];
193
    }
194
195
    private $underscores = [];
196
197
    public function toUnderscore($input)
198
    {
199
        if (!array_key_exists($input, $this->underscores)) {
200
            preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
201
            $ret = $matches[0];
202
            foreach ($ret as &$match) {
203
                $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
204
            }
205
            $this->underscores[$input] = implode('_', $ret);
206
        }
207
        return $this->underscores[$input];
208
    }
209
210
    private $camelcase = [];
211
212
    public function toCamelCase($input)
213
    {
214
        if (!array_key_exists($input, $this->camelcase)) {
215
            $this->camelcase[$input] = lcfirst(implode('', array_map('ucfirst', explode('_', $input))));
216
        }
217
        return $this->camelcase[$input];
218
    }
219
}
220