Completed
Push — master ( ce7ef8...bb3bdb )
by Dmitry
04:05
created

Procedure::validatePresence()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 9.2
c 0
b 0
f 0
cc 3
eloc 14
nc 2
nop 1
1
<?php
2
3
namespace Tarantool\Mapper\Plugin;
4
5
use Tarantool\Mapper\Plugin;
6
use Tarantool\Mapper\Procedure as BaseProcedure;
7
use Exception;
8
9
class Procedure extends Plugin
10
{
11
    public function get($class)
12
    {
13
        return $this->register($class);
14
    }
15
16
    public function invoke(BaseProcedure $procedure, $params)
17
    {
18
        $name = $procedure->getName();
19
        $this->validatePresence($procedure);
20
        $result = $this->mapper->getClient()->call($name, $params);
21
        return $result->getData()[0];
22
    }
23
24
    public function isRegistered($class)
25
    {
26
        return !!$this->mapper->findOne('_procedure', ['name' => $class]);
27
    }
28
29
    public function register($class)
30
    {
31
        if (!is_subclass_of($class, BaseProcedure::class)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Tarantool\Mapper\Procedure::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
32
            throw new Exception("Procedure should extend ".BaseProcedure::class.' class');
33
        }
34
        $this->initSchema();
35
36
        $procedure = new $class($this);
37
        $this->validatePresence($procedure);
38
        return $procedure;
39
    }
40
41
    private function validatePresence(BaseProcedure $procedure)
42
    {
43
        $name = $procedure->getName();
44
        $exists = $this->mapper->getClient()->evaluate("return _G.$name ~= nil")->getData()[0];
45
46
        $instance = $this->mapper->findOrCreate('_procedure', [
47
            'name' => get_class($procedure)
48
        ]);
49
50
        if ($instance->hash != md5($procedure->getBody()) || !$exists) {
51
            $params = implode(', ', $procedure->getParams());
52
            $body = $procedure->getBody();
53
54
            $script = "
55
            $name = function($params) $body end
56
            box.schema.func.create('$name', {if_not_exists=true})
57
            ";
58
            $this->mapper->getClient()->evaluate($script);
59
            $instance->hash = md5($body);
60
            $instance->save();
61
        }
62
    }
63
64
    private function initSchema()
65
    {
66
        $this->mapper->getSchema()->once(__CLASS__, function ($mapper) {
67
            $mapper->getSchema()
68
                ->createSpace('_procedure')
69
                ->addProperties([
70
                    'name' => 'string',
71
                    'hash' => 'string',
72
                ])
73
                ->addIndex([
74
                    'fields' => ['name'],
75
                    'type' => 'hash',
76
                ]);
77
        });
78
    }
79
}
80