Completed
Push — develop ( 2e41bf...bd9eae )
by Michael
04:29
created

AbstractActiveRecord   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 301
Duplicated Lines 11.96 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 13
Bugs 3 Features 3
Metric Value
wmc 35
c 13
b 3
f 3
lcom 1
cbo 3
dl 36
loc 301
ccs 115
cts 115
cp 1
rs 9

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A create() 0 14 2
A read() 0 21 3
A update() 17 17 3
A delete() 19 19 3
A sync() 0 8 2
A exists() 0 4 1
A fill() 0 12 3
A searchOne() 0 17 3
A search() 0 20 3
A getSearchQueryResult() 0 11 1
A getSearchQueryWhere() 0 8 2
A getSearchQueryOrderBy() 0 8 2
A getSearchQueryLimit() 0 9 2
A getPdo() 0 4 1
A setPdo() 0 6 1
A getId() 0 4 1
A setId() 0 6 1
getActiveRecordTable() 0 1 ?
getActiveRecordColumns() 0 1 ?

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 pdo active record with the given pdo.
30
	 *
31
	 * @param \PDO $pdo
32
	 */
33 31
	public function __construct(\PDO $pdo)
34
	{
35 31
		$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
36 31
		$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
37
38 31
		$this->setPdo($pdo);
39 31
	}
40
41
	/**
42
	 * {@inheritdoc}
43
	 */
44 4
	public function create()
45
	{
46
		try {
47 4
			$queryResult = (new Query($this->getPdo(), $this->getActiveRecordTable()))
0 ignored issues
show
Unused Code introduced by
$queryResult is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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 9
	public function read($id)
63
	{
64
		try {
65 9
			$result = (new Query($this->getPdo(), $this->getActiveRecordTable()))
66 9
				->select()
67 9
				->where('id', '=', $id)
68 9
				->execute()
69 8
				->fetch();
70
71 8
			if ($result === 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 7
			$this->fill($result);
76 6
			$this->setId($id);
77 9
		} catch (\PDOException $e) {
78 1
			throw new ActiveRecordException($e->getMessage(), 0, $e);
79
		}
80
81 6
		return $this;
82
	}
83
84
	/**
85
	 * {@inheritdoc}
86
	 */
87 5 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...
88
	{
89 5
		if (!$this->exists()) {
90 1
			throw new ActiveRecordException(sprintf('Can not update a non-existent active record entry to the `%s` table.', $this->getActiveRecordTable()));
91
		}
92
93
		try {
94 4
			$queryResult = (new Query($this->getPdo(), $this->getActiveRecordTable()))
0 ignored issues
show
Unused Code introduced by
$queryResult is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
95 4
				->update($this->getActiveRecordColumns())
96 4
				->where('id', '=', $this->getId())
97 4
				->execute();
98 4
		} catch (\PDOException $e) {
99 2
			throw new ActiveRecordException($e->getMessage(), 0, $e);
100
		}
101
102 2
		return $this;
103
	}
104
105
	/**
106
	 * {@inheritdoc}
107
	 */
108 4 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...
109
	{
110 4
		if (!$this->exists()) {
111 1
			throw new ActiveRecordException(sprintf('Can not delete a non-existent active record entry from the `%s` table.', $this->getActiveRecordTable()));
112
		}
113
114
		try {
115 3
			$queryResult = (new Query($this->getPdo(), $this->getActiveRecordTable()))
0 ignored issues
show
Unused Code introduced by
$queryResult is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
116 3
				->delete()
117 3
				->where('id', '=', $this->getId())
118 3
				->execute();
119
120 2
			$this->setId(null);
121 3
		} catch (\PDOException $e) {
122 1
			throw new ActiveRecordException($e->getMessage(), 0, $e);
123
		}
124
125 2
		return $this;
126
	}
127
128
	/**
129
	 * {@inheritdoc}
130
	 */
131 2
	public function sync()
132
	{
133 2
		if (!$this->exists()) {
134 1
			return $this->create();
135
		}
136
137 1
		return $this->update();
138
	}
139
140
	/**
141
	 * {@inheritdoc}
142
	 */
143 10
	public function exists()
144
	{
145 10
		return $this->getId() !== null;
146
	}
147
148
	/**
149
	 * Fill the active record
150
	 *
151
	 * @param array $fetch
152
	 * @return null
153
	 */
154 17
	public function fill(array $fetch)
155
	{
156 17
		$data = $this->getActiveRecordColumns();
157
158 17
		foreach ($data as $key => &$value) {
159 17
			if (!array_key_exists($key, $fetch)) {
160 1
				throw new ActiveRecordException(sprintf('Can not read the expected column `%s`. It\'s not returnd by the `%s` table', $key, $this->getActiveRecordTable()));
161
			}
162
163 17
			$value = $fetch[$key];
164 17
		}
165 16
	}
166
167
	/**
168
	 * {@inheritdoc}
169
	 */
170 28
	public function searchOne(array $where = [], array $orderBy = [])
171
	{
172
		try {
173 3
			$result = $this->getSearchQueryResult($where, $orderBy, 1)->fetch();
174
175 2
			if ($result === false) {
176 1
				throw new ActiveRecordException(sprintf('Can not search one non-existent entry from the `%s` table.', $this->getActiveRecordTable()));
177
			}
178
179 1
			$this->fill($result);
180 28
			$this->setId(intval($result['id']));
181
182 1
			return $this;
183 3
		} catch (\PDOException $e) {
184 1
			throw new ActiveRecordException($e->getMessage(), 0, $e);
185
		}
186
	}
187
188
	/**
189
	 * {@inheritdoc}
190
	 */
191 10
	public function search(array $where = [], array $orderBy = [], $limit = -1, $offset = 0)
192
	{
193
		try {
194 10
			$queryResult = $this->getSearchQueryResult($where, $orderBy, $limit, $offset);
195 8
			$result = [];
196
197 8
			foreach ($queryResult as $fetch) {
198 8
				$new = new static($this->getPdo());
199
200 8
				$new->setId(intval($fetch['id']));
201 8
				$new->fill($fetch);
202
203 8
				$result[] = $new;
204 8
			}
205
206 8
			return $result;
207 2
		} catch (\PDOException $e) {
208 2
			throw new ActiveRecordException($e->getMessage(), 0, $e);
209
		}
210
	}
211
212
	/**
213
	 * Returns the search query result with the given where, order by, limit and offset clauses.
214
	 *
215
	 * @param array $where = []
216
	 * @param array $orderBy = []
217
	 * @param int $limit = -1
218
	 * @param int $offset = 0
219
	 * @return Query the search query result with the given where, order by, limit and offset clauses.
0 ignored issues
show
Documentation introduced by
Should the return type not be \miBadger\Query\QueryResult?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
220
	 */
221 13
	private function getSearchQueryResult(array $where = [], array $orderBy = [], $limit = -1, $offset = 0)
222
	{
223 13
		$query = (new Query($this->getPdo(), $this->getActiveRecordTable()))
224 13
			->select();
225
226 13
		$this->getSearchQueryWhere($query, $where);
227 13
		$this->getSearchQueryOrderBy($query, $orderBy);
228 13
		$this->getSearchQueryLimit($query, $limit, $offset);
229
230 13
		return $query->execute();
231
	}
232
233 13
	private function getSearchQueryWhere($query, $where)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
234
	{
235 13
		foreach ($where as $key => $value) {
236 7
			$query->where($value[0], $value[1], $value[2]);
237 13
		}
238
239 13
		return $query;
240
	}
241
242 13
	private function getSearchQueryOrderBy($query, $orderBy)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
243
	{
244 13
		foreach ($orderBy as $key => $value) {
245 1
			$query->orderBy($key, $value);
246 13
		}
247
248 13
		return $query;
249
	}
250
251 13
	private function getSearchQueryLimit($query, $limit, $offset)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
252
	{
253 13
		if ($limit > -1) {
254 5
			$query->limit($limit);
255 5
			$query->offset($offset);
256 5
		}
257
258 13
		return $query;
259
	}
260
261
	/**
262
	 * Returns the PDO.
263
	 *
264
	 * @return \PDO the PDO.
265
	 */
266 28
	public function getPdo()
267
	{
268 28
		return $this->pdo;
269
	}
270
271
	/**
272
	 * Set the PDO.
273
	 *
274
	 * @param \PDO $pdo
275
	 * @return $this
276
	 */
277 31
	protected function setPdo($pdo)
278
	{
279 31
		$this->pdo = $pdo;
280
281 31
		return $this;
282
	}
283
284
	/**
285
	 * Returns the ID.
286
	 *
287
	 * @return null|int The ID.
288
	 */
289 9
	public function getId()
290
	{
291 9
		return $this->id;
292
	}
293
294
	/**
295
	 * Set the ID.
296
	 *
297
	 * @param int $id
298
	 * @return $this
299
	 */
300 16
	protected function setId($id)
301
	{
302 16
		$this->id = $id;
303
304 16
		return $this;
305
	}
306
307
	/**
308
	 * Returns the active record table.
309
	 *
310
	 * @return string the active record table.
311
	 */
312
	abstract protected function getActiveRecordTable();
313
314
	/**
315
	 * Returns the active record columns.
316
	 *
317
	 * @return array the active record columns.
318
	 */
319
	abstract protected function getActiveRecordColumns();
320
}
321