Completed
Push — master ( dcba90...2ccedc )
by Dmitry
03:50
created

Repository::find()   D

Complexity

Conditions 9
Paths 24

Size

Total Lines 40
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 9

Importance

Changes 4
Bugs 1 Features 0
Metric Value
c 4
b 1
f 0
dl 0
loc 40
ccs 31
cts 31
cp 1
rs 4.909
cc 9
eloc 26
nc 24
nop 2
crap 9
1
<?php
2
3
namespace Tarantool\Mapper;
4
5
use Tarantool\Mapper\Contracts;
6
use BadMethodCallException;
7
use LogicException;
8
9
class Repository implements Contracts\Repository
10
{
11
    protected $type;
12
    protected $entities = [];
13
    protected $keyMap = [];
14
15
    protected $magicMethodRules = [
16
        'by' => false,
17
        'firstBy' => true,
18
        'oneBy' => true
19
    ];
20
21 4
    public function __construct(Contracts\Type $type)
22
    {
23 4
        $this->type = $type;
24 4
    }
25
26 4
    public function make(array $data = null)
27
    {
28 4
        return $this->register(new Entity($data));
29
    }
30
31 4
    public function __call($method, $arguments)
32
    {
33 4
        foreach ($this->magicMethodRules as $prefix => $oneItem) {
34 4
            if (substr($method, 0, strlen($prefix)) == $prefix) {
35 4
                $tail = substr($method, strlen($prefix));
36 4
                $fields = array_map('strtolower', explode('And', $tail));
37 4
                return $this->find(array_combine($fields, $arguments), $oneItem);
38
            }
39 4
        }
40
41
        throw new BadMethodCallException("Method $method not found");
42
    }
43
44 4
    public function find($params = [], $oneItem = false)
45
    {
46 4
        $fields = array_keys($params);
47 4
        $values = [];
48
49 4
        sort($fields);
50 4
        foreach($fields as $field) {
51 4
            $values[] = $params[$field];
52 4
        }
53
54 4
        $index = implode('_', $fields);
55
56 4
        if(!$index) {
57 1
            $index = 'id';
58 1
        }
59
60 4
        $space = $this->type->getManager()->getClient()->getSpace($this->type->getName());
61 4
        $data = $space->select($values, $index);
62
63 4
        $result = [];
64 4
        if (!empty($data->getData())) {
65 4
            foreach ($data->getData() as $tuple) {
66 4
                $data = $this->type->decode($tuple);
67 4
                if (isset($data['id']) && array_key_exists($data['id'], $this->keyMap)) {
68 4
                    $entity = $this->entities[$this->keyMap[$data['id']]];
69 4
                    $entity->update($data);
70 4
                } else {
71 4
                    $entity = new Entity($data);
72 4
                    $this->register($entity);
73
                }
74 4
                if ($oneItem) {
75 4
                    return $entity;
76
                }
77 4
                $result[] = $entity;
78 4
            }
79 4
        }
80 4
        if (!$oneItem) {
81 4
            return $result;
82
        }
83 4
    }
84
85
    /**
86
     * @return Entity
87
     */
88 4
    public function knows(Contracts\Entity $entity)
89
    {
90 4
        return in_array($entity, $this->entities);
91
    }
92
93 4
    public function save(Contracts\Entity $entity)
94
    {
95 4
        if (!$this->knows($entity)) {
96
            throw new LogicException("Entity is not related with this repository");
97
        }
98
99 4
        if (!$entity->getId()) {
100 4
            $this->generateId($entity);
101 4
            $tuple = $this->type->encode($entity->toArray());
102 4
            $this->type->getSpace()->insert($tuple);
103 4
        } else {
104 1
            $changes = $entity->pullChanges();
105 1
            if (count($changes)) {
106 1
                $operations = [];
107 1
                foreach ($this->type->encode($changes) as $key => $value) {
108 1
                    $operations[] = ['=', $key + 1, $value];
109 1
                }
110 1
                $this->type->getSpace()->update($entity->getId(), $operations);
111 1
            }
112
        }
113
114 4
        return $entity;
115
    }
116
117 4
    protected function register(Contracts\Entity $entity)
118
    {
119 4
        if (!$this->knows($entity)) {
120 4
            $this->entities[] = $entity;
121 4
        }
122 4
        if ($entity->getId() && !array_key_exists($entity->getId(), $this->keyMap)) {
123 4
            $this->keyMap[$entity->getId()] = array_search($entity, $this->entities);
124 4
        }
125 4
        return $entity;
126
    }
127
128 4
    protected function generateId(Contracts\Entity $entity)
129
    {
130 4
        $manager = $this->type->getManager();
131 4
        $name = $this->type->getName();
132
133 4
        $sequence = $manager->get('sequences')->oneByName($name);
134 4
        if (!$sequence) {
135 4
            $sequence = $manager->get('sequences')->make([
136 4
                'name' => $name,
137 4
                'value' => 0,
138 4
            ]);
139 4
            $manager->save($sequence);
140 4
        }
141
142 4
        $nextValue = $manager->getClient()
143 4
            ->getSpace('sequences')
144 4
            ->update($sequence->id, [['+', 2, 1]])
145 4
            ->getData()[0][2];
146
147 4
        $entity->setId($nextValue);
148
149 4
        $this->register($entity);
150
151 4
        return $entity;
152
    }
153
}
154