Passed
Push — master ( 40b137...b03450 )
by Pauli
02:02
created

BaseMapper::selectUserEntities()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 8
ccs 0
cts 5
cp 0
crap 6
rs 10
1
<?php
2
3
/**
4
 * ownCloud - Music app
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Pauli Järvinen <[email protected]>
10
 * @copyright Pauli Järvinen 2016 - 2020
11
 */
12
13
namespace OCA\Music\Db;
14
15
use OCP\AppFramework\Db\Mapper;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Db\Mapper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
use OCP\IDBConnection;
0 ignored issues
show
Bug introduced by
The type OCP\IDBConnection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
18
use \Doctrine\DBAL\Exception\UniqueConstraintViolationException;
0 ignored issues
show
Bug introduced by
The type Doctrine\DBAL\Exception\...raintViolationException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
20
/**
21
 * Common base class for data access classes of the Music app
22
 */
23
abstract class BaseMapper extends Mapper {
24
25
	const SQL_DATE_FORMAT = 'Y-m-d H:i:s';
26
27
	protected $nameColumn;
28
29
	/**
30
	 * @param IDBConnection $db
31
	 * @param string $tableName
32
	 * @param string $entityClass
33
	 */
34
	public function __construct(IDBConnection $db, $tableName, $entityClass, $nameColumn) {
35
		parent::__construct($db, $tableName, $entityClass);
36
		$this->nameColumn = $nameColumn;
37
	}
38
39
	/**
40
	 * Find a single entity by id and user_id
41
	 * @param integer $id
42
	 * @param string $userId
43
	 * @throws DoesNotExistException if the entity does not exist
44
	 * @throws MultipleObjectsReturnedException if more than one entity exists
45
	 * @return Entity
0 ignored issues
show
Bug introduced by
The type OCA\Music\Db\Entity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
46
	 */
47
	public function find($id, $userId) {
48
		$sql = $this->selectUserEntities('`id` = ?');
49
		return $this->findEntity($sql, [$userId, $id]);
50
	}
51
52
	/**
53
	 * Find all entities matching the given IDs. Specifying the owning user is optional.
54
	 * @param integer[] $ids  IDs of the entities to be found
55
	 * @param string|null $userId
56
	 * @return Entity[]
57
	 */
58
	public function findById($ids, $userId=null) {
59
		$count = \count($ids);
60
		$condition = '`id` IN '. $this->questionMarks($count);
61
62
		if (empty($userId)) {
63
			$sql = $this->selectEntities($condition);
64
		} else {
65
			$sql = $this->selectUserEntities($condition);
66
			$ids = \array_merge([$userId], $ids);
67
		}
68
69
		return $this->findEntities($sql, $ids);
70
	}
71
72
	/**
73
	 * Find all user's entities
74
	 * 
75
	 * @param string $userId
76
	 * @param integer $sortBy sort order of the result set
77
	 * @param integer|null $limit
78
	 * @param integer|null $offset
79
	 * @return Entity[]
80
	 */
81
	public function findAll($userId, $sortBy=SortBy::None, $limit=null, $offset=null) {
82
		$sql = $this->selectUserEntities(
83
				'', $sortBy == SortBy::Name ? "ORDER BY LOWER(`{$this->nameColumn}`)" : null);
84
		$params = [$userId];
85
		return $this->findEntities($sql, $params, $limit, $offset);
86
	}
87
88
	/**
89
	 * Find all user's entities matching the given name
90
	 * 
91
	 * @param string|null $name
92
	 * @param string $userId
93
	 * @param bool $fuzzy
94
	 * @param integer|null $limit
95
	 * @param integer|null $offset
96
	 * @return Artist[]
97
	 */
98
	public function findAllByName($name, $userId, $fuzzy = false, $limit=null, $offset=null) {
99
		$nameCol = $this->nameColumn;
100
		if ($name === null) {
101
			$condition = "`$nameCol` IS NULL";
102
			$params = [$userId];
103
		} elseif ($fuzzy) {
104
			$condition = "LOWER(`$nameCol`) LIKE LOWER(?)";
105
			$params = [$userId, "%$name%"];
106
		} else {
107
			$condition = "`$nameCol` = ?";
108
			$params = [$userId, $name];
109
		}
110
		$sql = $this->selectUserEntities($condition, "ORDER BY LOWER(`$nameCol`)");
111
112
		return $this->findEntities($sql, $params, $limit, $offset);
113
	}
114
115
	/**
116
	 * Find all user's starred entities
117
	 * 
118
	 * @param string $userId
119
	 * @param integer|null $limit
120
	 * @param integer|null $offset
121
	 * @return Entity[]
122
	 */
123
	public function findAllStarred($userId, $limit=null, $offset=null) {
124
		$sql = $this->selectUserEntities('`starred` IS NOT NULL', "ORDER BY LOWER(`{$this->nameColumn}`)");
125
		return $this->findEntities($sql, [$userId], $limit, $offset);
126
	}
127
128
	/**
129
	 * Delete all entities with given IDs without specifying the user
130
	 * @param integer[] $ids  IDs of the entities to be deleted
131
	 */
132
	public function deleteById($ids) {
133
		$count = \count($ids);
134
		if ($count === 0) {
135
			return;
136
		}
137
		$sql = 'DELETE FROM `' . $this->getTableName() . '` WHERE `id` IN '. $this->questionMarks($count);
138
		$this->execute($sql, $ids);
139
	}
140
141
	/**
142
	 * Count all entities of a user
143
	 * @param string $userId
144
	 */
145
	public function count($userId) {
146
		$sql = 'SELECT COUNT(*) AS count FROM `' . $this->getTableName() . '` '.
147
			'WHERE `user_id` = ?';
148
		$result = $this->execute($sql, [$userId]);
149
		$row = $result->fetch();
150
		return \intval($row['count']);
151
	}
152
153
	/**
154
	 * Insert an entity, or if an entity with the same identity already exists,
155
	 * update the existing entity.
156
	 * @param Entity $entity
157
	 * @return Entity The inserted or updated entity, containing also the id field
158
	 */
159
	public function insertOrUpdate($entity) {
160
		try {
161
			return $this->insert($entity);
162
		} catch (UniqueConstraintViolationException $ex) {
163
			$existingEntity = $this->findUniqueEntity($entity);
164
			$entity->setId($existingEntity->getId());
165
			return $this->update($entity);
166
		}
167
	}
168
169
	/**
170
	 * Set the "starred" column of the given entities
171
	 * @param DateTime|null $date
0 ignored issues
show
Bug introduced by
The type OCA\Music\Db\DateTime was not found. Did you mean DateTime? If so, make sure to prefix the type with \.
Loading history...
172
	 * @param integer[] $ids
173
	 * @param string $userId
174
	 */
175
	public function setStarredDate($date, $ids, $userId) {
176
		$count = \count($ids);
177
		if (!empty($date)) {
178
			$date = $date->format(self::SQL_DATE_FORMAT);
179
		}
180
181
		$sql = "UPDATE `{$this->getTableName()}` SET `starred` = ? " .
182
				"WHERE `id` IN {$this->questionMarks($count)} AND `user_id` = ?";
183
		$params = \array_merge([$date], $ids, [$userId]);
184
		$this->execute($sql, $params);
185
	}
186
187
	/**
188
	 * helper creating a string like '(?,?,?)' with the specified number of elements
189
	 * @param int $count
190
	 */
191
	protected function questionMarks($count) {
192
		$questionMarks = [];
193
		for ($i = 0; $i < $count; $i++) {
194
			$questionMarks[] = '?';
195
		}
196
		return '(' . \implode(',', $questionMarks) . ')';
197
	}
198
199
	/**
200
	 * Build a SQL SELECT statement which selects all entities of the given user,
201
	 * and optionally applies other conditions, too.
202
	 * This is built upon `selectEntities` which may be overridden by the derived class.
203
	 * @param string|null $condition Optional extra condition. This will get automatically
204
	 *                               prefixed with ' AND ', so don't include that.
205
	 * @param string|null $extension Any extension (e.g. ORDER BY, LIMIT) to be added after
206
	 *                               the conditions in the SQL statement
207
	 */
208
	protected function selectUserEntities($condition=null, $extension=null) {
209
		$allConditions = '`user_id` = ?';
210
211
		if (!empty($condition)) {
212
			$allConditions .= " AND $condition";
213
		}
214
215
		return $this->selectEntities($allConditions, $extension);
216
	}
217
218
	/**
219
	 * Build a SQL SELECT statement which selects all entities matching the given condition.
220
	 * The derived class may override this if necessary.
221
	 * @param string $condition This will get automatically prefixed with ' WHERE '
222
	 * @param string|null $extension Any extension (e.g. ORDER BY, LIMIT) to be added after
223
	 *                               the conditions in the SQL statement
224
	 */
225
	protected function selectEntities($condition, $extension=null) {
226
		return "SELECT * FROM `{$this->getTableName()}` WHERE $condition $extension ";
227
	}
228
229
	/**
230
	 * Find an entity which has the same identity as the supplied entity.
231
	 * How the identity of the entity is defined, depends on the derived concrete class.
232
	 * @param Entity $entity
233
	 * @return Entity
234
	 */
235
	abstract protected function findUniqueEntity($entity);
236
}
237