Passed
Branch v1.5.1 (056dca)
by Wanderson
01:53
created

Orm::raw()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Win\Repositories\Database;
4
5
use Win\Common\Pagination;
6
use Win\Models\Model;
7
8
/**
9
 * Object Relational Mapping
10
 */
11
abstract class Orm
12
{
13
	/** @var string */
14
	const TABLE = '';
15
16
	/** @var string */
17
	const TITLE = '';
18
19
	/** @var string */
20
	const PK = 'id';
21
22
	/** @var Connection */
23
	public $conn;
24
25
	/** @var Pagination */
26
	public $pagination;
27
28
	/** @var Query */
29
	protected $query;
30
31
	/**
32
	 * @param Model $model
33
	 * @return mixed[]
34
	 */
35
	abstract public static function mapRow($model);
36
37
	abstract public static function mapModel($row);
38
39
	/**
40
	 * @param Connection $connection
41
	 */
42
	public function __construct($connection = null)
43
	{
44
		$this->conn = $connection ?: MysqlConnection::instance();
45
		$this->query = new Query(static::TABLE);
46
		$this->pagination = new Pagination();
47
	}
48
49
	/**
50
	 * Prepara raw Sql
51
	 * @param string $query
52
	 * @param mixed[]
53
	 */
54
	public function raw($query, $values = [])
55
	{
56
		$this->query = new Query(static::TABLE, $values, $query);
57
58
		return $this;
59
	}
60
61
	/**
62
	 * Executa SQL
63
	 * @param string $query
64
	 * @param mixed[]
65
	 */
66
	public function execute($query, $values = [])
67
	{
68
		return $this->conn->execute($query, $values);
69
	}
70
71
	/**
72
	 * Retorna o primeiro resultado da busca
73
	 */
74
	public function one()
75
	{
76
		$this->query->setLimit(0, 1);
77
78
		$query = $this->query->select();
79
		$values = $this->query->getValues();
80
		$row = $this->conn->fetch($query, $values);
81
		$this->flush();
82
83
		return $this->mapModel($row);
84
	}
85
86
	/**
87
	 * Retorna o registro pela PK
88
	 * @param int $id
89
	 */
90
	public function find($id)
91
	{
92
		return $this->filterBy(static::PK, $id)->one();
93
	}
94
95
	/**
96
	 * Retorna o todos os resultados da busca
97
	 */
98
	public function list()
99
	{
100
		$this->applyPagination();
101
102
		$query = $this->query->select();
103
		$values = $this->query->getValues();
104
		$rows = $this->conn->fetchAll($query, $values);
105
		$this->flush();
106
107
		return array_map([$this, 'mapModel'], $rows);
108
	}
109
110
	/**
111
	 * Retorna o total de resultados da busca
112
	 * Sem aplicar LIMIT e FLUSH
113
	 */
114
	public function count()
115
	{
116
		$query = $this->query->selectCount();
117
		$values = $this->query->getValues();
118
119
		return $this->conn->fetchCount($query, $values);
120
	}
121
122
	/**
123
	 * Remove todos os registros da busca
124
	 */
125
	public function delete()
126
	{
127
		$query = $this->query->delete();
128
		$values = $this->query->getValues();
129
		$this->conn->execute($query, $values);
130
		$this->flush();
131
	}
132
133
	/**
134
	 * Remove o registro pela PK
135
	 * @param int $id
136
	 */
137
	public function destroy($id)
138
	{
139
		$this->filterBy(static::PK, $id);
140
141
		$query = $this->query->delete();
142
		$values = $this->query->getValues();
143
		$this->conn->execute($query, $values);
144
		$this->flush();
145
	}
146
147
	/**
148
	 * Salva o registro no banco
149
	 * @param Model $model
150
	 */
151
	public function save(Model $model)
152
	{
153
		$model->validate();
154
		if ($this->exists($model)) {
155
			$this->update($model);
156
		} else {
157
			$this->insert($model);
158
		};
159
		$this->flush();
160
161
		return $model;
162
	}
163
164
	/**
165
	 * Remove todos os filtros, ordenação, etc
166
	 */
167
	public function flush()
168
	{
169
		$this->query = new Query(static::TABLE);
170
171
		return $this;
172
	}
173
174
	/**
175
	 * @param Model $model
176
	 */
177
	private function insert($model)
178
	{
179
		$this->query = new Query(static::TABLE, $this->mapRow($model));
180
		$query = $this->query->insert();
181
		$values = $this->query->getValues();
182
		$this->conn->execute($query, $values);
183
184
		$model->id = (int) $this->conn->getLastInsertId();
185
	}
186
187
	/**
188
	 * @param Model $model
189
	 */
190
	private function update($model)
191
	{
192
		$this->query = new Query(static::TABLE, $this->mapRow($model));
193
		$this->filterBy(static::PK, $model->id);
194
195
		$query = $this->query->update();
196
		$values = $this->query->getValues();
197
		$this->conn->execute($query, $values);
198
		$this->flush();
199
	}
200
201
	/**
202
	 * Retorna TRUE se o model existir no banco
203
	 * @return bool
204
	 */
205
	protected function exists($model)
206
	{
207
		$orm = new static($this->conn);
208
		$orm->filterBy(static::PK, $model->id);
209
210
		return $orm->count() > 0;
211
	}
212
213
	/**
214
	 * Aplica um filtro ($comparator aceita mais de uma regra)
215
	 * @param string $comparator
216
	 * @param mixed $value
217
	 * @example filterBy('name = ? AND email = ?', 'John', '[email protected]')
218
	 */
219
	public function filterBy($comparator, ...$values)
220
	{
221
		$this->query->addWhere($comparator, ...$values);
222
223
		return $this;
224
	}
225
226
	/**
227
	 * Ordem por um campo
228
	 * @param string $column
229
	 * @param string $mode 'ASC' | 'DESC'
230
	 * @param int $priority
231
	 */
232
	public function sortBy($column, $mode = 'ASC', $priority = 0)
233
	{
234
		$this->query->addOrderBy($column . ' ' . $mode, $priority);
235
236
		return $this;
237
	}
238
239
	public function sortNewest()
240
	{
241
		return $this->sortBy('id', 'DESC');
242
	}
243
244
	public function sortOldest()
245
	{
246
		return $this->sortBy('id', 'ASC');
247
	}
248
249
	public function sortRand()
250
	{
251
		return $this->sortBy('RAND()');
252
	}
253
254
	/**
255
	 * @param int $pageSize
256
	 * @param int $pageNumber
257
	 */
258
	public function paginate($pageSize, $pageNumber = 1)
259
	{
260
		$this->pagination->setPage($pageSize, $pageNumber);
261
262
		return $this;
263
	}
264
265
	/**
266
	 * Define a paginação se necessário
267
	 */
268
	private function applyPagination()
269
	{
270
		$count = $this->count();
271
		$pagination = $this->pagination;
272
273
		if ($pagination->pageSize() && $count) {
274
			$pagination->setCount($count);
275
			$this->query->setLimit($pagination->offset(), $pagination->pageSize());
276
		}
277
	}
278
279
	public function beginTransaction()
280
	{
281
		$this->conn->getPdo()->beginTransaction();
282
	}
283
284
	/**
285
	 * Completa a Transação
286
	 */
287
	public function commit()
288
	{
289
		$this->conn->getPdo()->commit();
290
	}
291
292
	/**
293
	 * Cancela a Transação
294
	 */
295
	public function rollback()
296
	{
297
		$this->conn->getPdo()->rollBack();
298
	}
299
}
300