Passed
Branch v1.5.1 (94eede)
by Wanderson
02:06
created

Orm::commit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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