Completed
Push — master ( 4deaab...ecf49a )
by Joao
04:00 queued 01:34
created

Repository::processLiteral()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 6
nc 3
nop 2
crap 3
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: jg
5
 * Date: 21/06/16
6
 * Time: 16:17
7
 */
8
9
namespace ByJG\MicroOrm;
10
11
12
use ByJG\AnyDataset\DbDriverInterface;
13
use ByJG\Serializer\BinderObject;
14
15
class Repository
16
{
17
18
    /**
19
     * @var Mapper
20
     */
21
    protected $mapper;
22
23
    /**
24
     * @var DbDriverInterface
25
     */
26
    protected $dbDriver = null;
27
28
    protected $limitStart = null;
29
    protected $limitEnd = null;
30
    protected $top = null;
31
32
    /**
33
     * Repository constructor.
34
     * @param DbDriverInterface $dbDataset
35
     * @param Mapper $mapper
36
     */
37 19
    public function __construct(DbDriverInterface $dbDataset, Mapper $mapper)
38
    {
39 19
        $this->dbDriver = $dbDataset;
40 19
        $this->mapper = $mapper;
41 19
    }
42
43
    /**
44
     * @return Mapper
45
     */
46 8
    public function getMapper()
47
    {
48 8
        return $this->mapper;
49
    }
50
51
    /**
52
     * @return DbDriverInterface
53
     */
54 19
    protected function getDbDriver()
55
    {
56 19
        return $this->dbDriver;
57
    }
58
59
    /**
60
     * @param array|string $id
61
     * @return mixed|null
62
     */
63 14
    public function get($id)
64
    {
65 14
        $result = $this->getByFilter($this->mapper->getPrimaryKey() . ' = [[id]]', ['id' => $id]);
66
67 14
        if (count($result) === 1) {
68 14
            return $result[0];
69
        }
70
71 3
        return null;
72
    }
73
74
    /**
75
     * @param array $id
76
     * @return mixed|null
77
     */
78 2
    public function delete($id)
79
    {
80 2
        $params = ['id' => $id];
81 2
        $query = new Query();
82 2
        $query->table($this->mapper->getTable())
83 2
            ->where($this->mapper->getPrimaryKey() . ' = [[id]]', $params);
84
85 2
        return $this->deleteByQuery($query);
86
    }
87
88
    /**
89
     * @param $query
90
     * @return bool
91
     */
92 3
    public function deleteByQuery(Query $query)
93
    {
94 3
        $delete = $query->getDelete();
95 3
        $sql = $delete['sql'];
96 3
        $params = $delete['params'];
97
98 3
        if (is_array($params)) {
99 3
            $sql = $this->processLiteral($sql, $params);
100 3
        }
101
102 3
        $this->getDbDriver()->execute($sql, $params);
103
104 3
        return true;
105
    }
106
107 1
    public function limit($start, $end)
108
    {
109 1
        $this->limitStart = $start;
110 1
        $this->limitEnd = $end;
111 1
        $this->top = null;
112 1
        return $this;
113
    }
114
115 1
    public function top($top)
116
    {
117 1
        $this->top = $top;
118 1
        $this->limitStart = $this->limitEnd = null;
119
120 1
        return $this;
121
    }
122
123
    /**
124
     * @param string $filter
125
     * @param array $params
126
     * @param bool $forUpdate
127
     * @return array
128
     */
129 14
    public function getByFilter($filter, array $params, $forUpdate = false)
130
    {
131 14
        $query = new Query();
132 14
        $query->table($this->mapper->getTable())
133 14
            ->where($filter, $params);
134
        
135 14
        if ($forUpdate) {
136
            $query->forUpdate();
137
        }
138
139 14
        return $this->getByQuery($query);
140
    }
141
142
    /**
143
     * @param Query $query
144
     * @param Mapper[] $mapper
145
     * @return array
146
     */
147 19
    public function getByQuery(Query $query, array $mapper = [])
148
    {
149 19
        $mapper = array_merge([$this->mapper], $mapper);
150 19
        $query = $query->getSelect();
151
152 19
        if (!empty($this->top)) {
153 1
            $query['sql'] = $this->getDbDriver()->getDbHelper()->top($query['sql'], $this->top);
154 1
        }
155
156 19
        if (!empty($this->limitStart)) {
157 1
            $query['sql'] = $this->getDbDriver()->getDbHelper()->limit($query['sql'], $this->limitStart, $this->limitEnd);
158 1
        }
159
160 19
        $params = $query['params'];
161 19
        $sql = $query['sql'];
162 19
        if (is_array($params)) {
163 17
            $sql = $this->processLiteral($sql, $params);
164 17
        }
165 19
        $result = [];
166 19
        $iterator = $this->getDbDriver()->getIterator($sql, $params);
167
168 19
        foreach ($iterator as $row) {
169 19
            $collection = [];
170 19
            foreach ($mapper as $item) {
171 19
                $instance = $item->getEntity();
172 19
                $data = $row->toArray();
173
174 19
                BinderObject::bindObject($data, $instance);
175 19
                foreach ((array)$item->getFieldMap() as $property => $fieldmap) {
176 8
                    $selectMask = $fieldmap[Mapper::FIELDMAP_SELECTMASK];
177 8
                    $data[$property] = $selectMask($row->get($fieldmap[Mapper::FIELDMAP_FIELD]), $instance);
178 19
                }
179 19
                if (count($item->getFieldMap()) > 0) {
180 8
                    BinderObject::bindObject($data, $instance);
181 8
                }
182 19
                $collection[] = $instance;
183 19
            }
184 19
            $result[] = count($collection) === 1 ? $collection[0] : $collection;
185 19
        }
186
187 19
        $this->limitStart = $this->limitEnd = $this->top = null;
188
189 19
        return $result;
190
    }
191
192
    /**
193
     * @param mixed $instance
194
     */
195 8
    public function save($instance)
196
    {
197
        // Get all fields
198 8
        $array = BinderObject::toArrayFrom($instance, true);
199
200
        // Mapping the data
201 8
        foreach ((array)$this->getMapper()->getFieldMap() as $property => $fieldmap) {
202 3
            $fieldname = $fieldmap[Mapper::FIELDMAP_FIELD];
203 3
            $updateMask = $fieldmap[Mapper::FIELDMAP_UPDATEMASK];
204
205
            // If no value for UpdateMask, remove from the list;
206 3
            if (empty($updateMask)) {
207 2
                unset($array[$property]);
208 2
                continue;
209
            }
210
211
            // Get the value from the mapped field name
212 3
            $value = $array[$property];
213 3
            unset($array[$property]);
214 3
            $array[$fieldname] = $updateMask($value, $instance);
215 8
        }
216
217
        // Prepare query to insert
218 8
        $query = new Query();
219 8
        $query->table($this->mapper->getTable())
220 8
            ->fields(array_keys($array));
221
222
        // Check if is insert or update
223 8
        if (empty($array[$this->mapper->getPrimaryKey()]) || count($this->get($array[$this->mapper->getPrimaryKey()])) === 0)  {
224 5
            $array[$this->mapper->getPrimaryKey()] = $this->insert($query, $array);
225 5
            BinderObject::bindObject($array, $instance);
226 5
        } else {
227 3
            $this->update($query, $array);
228
        }
229 8
    }
230
231
    /**
232
     * @param Query $query
233
     * @param array $params
234
     * @return int
235
     * @throws \Exception
236
     */
237 5
    protected function insert(Query $query, array $params)
238
    {
239 5
        $keyGen = $this->getMapper()->generateKey();
240 5
        if (empty($keyGen)) {
241 4
            return $this->insertWithAutoinc($query, $params);
242
        } else {
243 1
            return $this->insertWithKeyGen($query, $params, $keyGen);
244
        }
245
    }
246
247 4
    protected function insertWithAutoinc(Query $query, array $params)
248
    {
249 4
        $sql = $this->processLiteral($query->getInsert($this->getDbDriver()->getDbHelper()), $params);
250 4
        $dbFunctions = $this->getDbDriver()->getDbHelper();
251 4
        return $dbFunctions->executeAndGetInsertedId($this->getDbDriver(), $sql, $params);
252
    }
253
254 1
    protected function insertWithKeyGen(Query $query, array $params, $keyGen)
255
    {
256 1
        $params[$this->mapper->getPrimaryKey()] = $keyGen;
257 1
        $sql = $this->processLiteral($query->getInsert($this->getDbDriver()->getDbHelper()), $params);
258 1
        $this->getDbDriver()->execute($sql, $params);
259 1
        return $keyGen;
260
    }
261
262
    /**
263
     * @param Query $query
264
     * @param array $params
265
     * @throws \Exception
266
     */
267 3
    protected function update(Query $query, array $params)
268
    {
269 3
        $params = array_merge($params, ['_id' => $params[$this->mapper->getPrimaryKey()]]);
270 3
        $query->where($this->mapper->getPrimaryKey() . ' = [[_id]] ', ['_id' => $params['_id']]);
271 3
        $update = $query->getUpdate($this->getDbDriver()->getDbHelper());
272 3
        $sql = $this->processLiteral($update['sql'], $params);
273
274 3
        $this->getDbDriver()->execute($sql, $params);
275 3
    }
276
277 17
    protected function processLiteral($sql, array &$params)
278
    {
279 17
        foreach ($params as $field => $param) {
280 17
            if ($param instanceof Literal) {
281 4
                $sql = str_replace('[[' . $field . ']]', $param->getLiteralValue(), $sql);
282 4
                unset($params[$field]);
283 4
            }
284 17
        }
285
286 17
        return $sql;
287
    }
288
}
289