Passed
Branch v1.5.1 (d792f9)
by Wanderson
01:51
created

Orm::exists()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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