Completed
Push — develop ( a0080e...d8ede3 )
by Michael
02:47
created

AbstractActiveRecord::search()   A

Complexity

Conditions 3
Paths 6

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 5
Bugs 0 Features 1
Metric Value
c 5
b 0
f 1
dl 0
loc 17
ccs 10
cts 10
cp 1
rs 9.4285
cc 3
eloc 10
nc 6
nop 4
crap 3
1
<?php
2
3
/**
4
 * This file is part of the miBadger package.
5
 *
6
 * @author Michael Webbers <[email protected]>
7
 * @license http://opensource.org/licenses/Apache-2.0 Apache v2 License
8
 * @version 1.0.0
9
 */
10
11
namespace miBadger\ActiveRecord;
12
13
use miBadger\Query\Query;
14
15
/**
16
 * The abstract active record class.
17
 *
18
 * @since 1.0.0
19
 */
20
abstract class AbstractActiveRecord implements ActiveRecordInterface
21
{
22
	/** @var \PDO The PDO object. */
23
	private $pdo;
24
25
	/** @var null|int The ID. */
26
	private $id;
27
28
	/**
29
	 * Construct an abstract active record with the given PDO.
30
	 *
31
	 * @param \PDO $pdo
32
	 */
33 28
	public function __construct(\PDO $pdo)
34
	{
35 28
		$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
36 28
		$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
37
38 28
		$this->setPdo($pdo);
39 28
	}
40
41
	/**
42
	 * {@inheritdoc}
43
	 */
44 4 View Code Duplication
	public function create()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
45
	{
46
		try {
47 4
			(new Query($this->getPdo(), $this->getActiveRecordTable()))
48 4
				->insert($this->getActiveRecordColumns())
49 4
				->execute();
50
51 2
			$this->setId(intval($this->getPdo()->lastInsertId()));
52 4
		} catch (\PDOException $e) {
53 2
			throw new ActiveRecordException($e->getMessage(), 0, $e);
54
		}
55
56 2
		return $this;
57
	}
58
59
	/**
60
	 * {@inheritdoc}
61
	 */
62 8
	public function read($id)
63
	{
64
		try {
65 8
			$row = (new Query($this->getPdo(), $this->getActiveRecordTable()))
66 8
				->select()
67 8
				->where('id', '=', $id)
68 8
				->execute()
69 7
				->fetch();
70
71 7
			if ($row === false) {
72 1
				throw new ActiveRecordException(sprintf('Can not read the non-existent active record entry %d from the `%s` table.', $id, $this->getActiveRecordTable()));
73
			}
74
75 6
			$this->fill($row)->setId($id);
76 8
		} catch (\PDOException $e) {
77 1
			throw new ActiveRecordException($e->getMessage(), 0, $e);
78
		}
79
80 6
		return $this;
81
	}
82
83
	/**
84
	 * {@inheritdoc}
85
	 */
86 4 View Code Duplication
	public function update()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
87
	{
88
		try {
89 4
			(new Query($this->getPdo(), $this->getActiveRecordTable()))
90 4
				->update($this->getActiveRecordColumns())
91 4
				->where('id', '=', $this->getId())
92 4
				->execute();
93 4
		} catch (\PDOException $e) {
94 2
			throw new ActiveRecordException($e->getMessage(), 0, $e);
95
		}
96
97 2
		return $this;
98
	}
99
100
	/**
101
	 * {@inheritdoc}
102
	 */
103 3 View Code Duplication
	public function delete()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
104
	{
105
		try {
106 3
			(new Query($this->getPdo(), $this->getActiveRecordTable()))
107 3
				->delete()
108 3
				->where('id', '=', $this->getId())
109 3
				->execute();
110
111 2
			$this->setId(null);
112 3
		} catch (\PDOException $e) {
113 1
			throw new ActiveRecordException($e->getMessage(), 0, $e);
114
		}
115
116 2
		return $this;
117
	}
118
119
	/**
120
	 * {@inheritdoc}
121
	 */
122 2
	public function sync()
123
	{
124 2
		if (!$this->exists()) {
125 1
			return $this->create();
126
		}
127
128 1
		return $this->update();
129
	}
130
131
	/**
132
	 * {@inheritdoc}
133
	 */
134 3
	public function exists()
135
	{
136 3
		return $this->getId() !== null;
137
	}
138
139
	/**
140
	 * {@inheritdoc}
141
	 */
142 16
	public function fill(array $attributes)
143
	{
144 16
		$columns = $this->getActiveRecordColumns();
145 16
		$columns['id'] = &$this->id;
146
147 16
		foreach ($attributes as $key => $value) {
148 16
			if (array_key_exists($key, $columns)) {
149 16
				$columns[$key] = $value;
150 16
			}
151 16
		}
152
153 16
		return $this;
154
	}
155
156
	/**
157
	 * {@inheritdoc}
158
	 */
159 3
	public function searchOne(array $where = [], array $orderBy = [])
160
	{
161
		try {
162 3
			$row = $this->getSearchQueryResult($where, $orderBy, 1)->fetch();
163
164 2
			if ($row === false) {
165 1
				throw new ActiveRecordException(sprintf('Can not search one non-existent entry from the `%s` table.', $this->getActiveRecordTable()));
166
			}
167
168 1
			return $this->fill($row)->setId($row['id']);
169 2
		} catch (\PDOException $e) {
170 1
			throw new ActiveRecordException($e->getMessage(), 0, $e);
171
		}
172
	}
173
174
	/**
175
	 * {@inheritdoc}
176
	 */
177 27
	public function search(array $where = [], array $orderBy = [], $limit = -1, $offset = 0)
178
	{
179
		try {
180 27
			$queryResult = $this->getSearchQueryResult($where, $orderBy, $limit, $offset);
181 8
			$result = [];
182
183 8
			foreach ($queryResult as $row) {
184 8
				$new = clone $this;
185
186 8
				$result[] = $new->fill($row)->setId($row['id']);
187 8
			}
188
189 8
			return $result;
190 2
		} catch (\PDOException $e) {
191 2
			throw new ActiveRecordException($e->getMessage(), 0, $e);
192
		}
193
	}
194
195
	/**
196
	 * Returns the search query result with the given where, order by, limit and offset clauses.
197
	 *
198
	 * @param array $where = []
199
	 * @param array $orderBy = []
200
	 * @param int $limit = -1
201
	 * @param int $offset = 0
202
	 * @return \miBadger\Query\QueryResult the search query result with the given where, order by, limit and offset clauses.
203
	 */
204 13
	private function getSearchQueryResult(array $where = [], array $orderBy = [], $limit = -1, $offset = 0)
205
	{
206 13
		$query = (new Query($this->getPdo(), $this->getActiveRecordTable()))
207 13
			->select();
208
209 13
		$this->getSearchQueryWhere($query, $where);
210 13
		$this->getSearchQueryOrderBy($query, $orderBy);
211 13
		$this->getSearchQueryLimit($query, $limit, $offset);
212
213 13
		return $query->execute();
214
	}
215
216
	/**
217
	 * Returns the given query after adding the given where conditions.
218
	 *
219
	 * @param \miBadger\Query\Query $query
220
	 * @param array $where
221
	 * @return \miBadger\Query\Query the given query after adding the given where conditions.
222
	 */
223 13
	private function getSearchQueryWhere($query, $where)
224
	{
225 13
		foreach ($where as $key => $value) {
226 7
			$query->where($value[0], $value[1], $value[2]);
227 13
		}
228
229 13
		return $query;
230
	}
231
232
	/**
233
	 * Returns the given query after adding the given order by conditions.
234
	 *
235
	 * @param \miBadger\Query\Query $query
236
	 * @param array $orderBy
237
	 * @return \miBadger\Query\Query the given query after adding the given order by conditions.
238
	 */
239 13
	private function getSearchQueryOrderBy($query, $orderBy)
240
	{
241 13
		foreach ($orderBy as $key => $value) {
242 1
			$query->orderBy($key, $value);
243 13
		}
244
245 13
		return $query;
246
	}
247
248
	/**
249
	 * Returns the given query after adding the given limit and offset conditions.
250
	 *
251
	 * @param \miBadger\Query\Query $query
252
	 * @param int $limit
253
	 * @param int $offset
254
	 * @return \miBadger\Query\Query the given query after adding the given limit and offset conditions.
255
	 */
256 13
	private function getSearchQueryLimit($query, $limit, $offset)
257
	{
258 13
		if ($limit > -1) {
259 5
			$query->limit($limit);
260 5
			$query->offset($offset);
261 5
		}
262
263 13
		return $query;
264
	}
265
266
	/**
267
	 * Returns the PDO.
268
	 *
269
	 * @return \PDO the PDO.
270
	 */
271 27
	public function getPdo()
272
	{
273 27
		return $this->pdo;
274
	}
275
276
	/**
277
	 * Set the PDO.
278
	 *
279
	 * @param \PDO $pdo
280
	 * @return $this
281
	 */
282 28
	protected function setPdo($pdo)
283
	{
284 28
		$this->pdo = $pdo;
285
286 28
		return $this;
287
	}
288
289
	/**
290
	 * Returns the ID.
291
	 *
292
	 * @return null|int The ID.
293
	 */
294 7
	public function getId()
295
	{
296 7
		return $this->id;
297
	}
298
299
	/**
300
	 * Set the ID.
301
	 *
302
	 * @param int $id
303
	 * @return $this
304
	 */
305 16
	protected function setId($id)
306
	{
307 16
		$this->id = $id;
308
309 16
		return $this;
310
	}
311
312
	/**
313
	 * Returns the active record table.
314
	 *
315
	 * @return string the active record table.
316
	 */
317
	abstract protected function getActiveRecordTable();
318
319
	/**
320
	 * Returns the active record columns.
321
	 *
322
	 * @return array the active record columns.
323
	 */
324
	abstract protected function getActiveRecordColumns();
325
}
326