Completed
Push — master ( 13dce9...b41dd5 )
by Dmitry
03:01
created

Repository::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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