Passed
Push — feature/909_Ampache_API_improv... ( a84036...a957d5 )
by Pauli
03:28
created

BusinessLayer::findAllRated()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 3
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
/**
3
 * ownCloud
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Alessandro Cosentino <[email protected]>
9
 * @author Bernhard Posselt <[email protected]>
10
 * @author Pauli Järvinen <[email protected]>
11
 * @copyright Alessandro Cosentino 2012
12
 * @copyright Bernhard Posselt 2012, 2014
13
 * @copyright Pauli Järvinen 2017 - 2023
14
 */
15
16
namespace OCA\Music\AppFramework\BusinessLayer;
17
18
use OCA\Music\Db\BaseMapper;
19
use OCA\Music\Db\Entity;
20
use OCA\Music\Db\MatchMode;
21
use OCA\Music\Db\SortBy;
22
use OCA\Music\Utility\Util;
23
24
use OCP\AppFramework\Db\DoesNotExistException;
25
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
26
27
/**
28
 * @phpstan-template EntityType of Entity
29
 */
30
abstract class BusinessLayer {
31
	protected $mapper;
32
33
	/**
34
	 * @phpstan-param BaseMapper<EntityType> $mapper
35
	 */
36
	public function __construct(BaseMapper $mapper) {
37
		$this->mapper = $mapper;
38
	}
39
40
	/**
41
	 * Update an entity in the database
42
	 * @phpstan-param EntityType $entity
43
	 * @phpstan-return EntityType
44
	 */
45
	public function update(Entity $entity) : Entity {
46
		return $this->mapper->update($entity);
47
	}
48
49
	/**
50
	 * Delete an entity
51
	 * @param int $id the id of the entity
52
	 * @param string $userId the name of the user for security reasons
53
	 * @throws BusinessLayerException if the entity does not exist or more than one entity exists
54
	 * @phpstan-return EntityType
55
	 */
56
	public function delete(int $id, string $userId) : Entity {
57
		$entity = $this->find($id, $userId);
58
		return $this->mapper->delete($entity);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...xtcloudMapper::delete() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

58
		return /** @scrutinizer ignore-deprecated */ $this->mapper->delete($entity);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
59
	}
60
61
	/**
62
	 * Deletes entities without specifying the owning user.
63
	 * This should never be called directly from the HTML API, but only in case
64
	 * we can actually trust the passed IDs (e.g. file deleted hook).
65
	 * @param array $ids the ids of the entities which should be deleted
66
	 */
67
	public function deleteById(array $ids) : void {
68
		if (\count($ids) > 0) {
69
			$this->mapper->deleteById($ids);
70
		}
71
	}
72
73
	/**
74
	 * Delete all entities of the given user
75
	 */
76
	public function deleteAll(string $userId) : void {
77
		$this->mapper->deleteAll($userId);
78
	}
79
80
	/**
81
	 * Finds an entity by id
82
	 * @param int $id the id of the entity
83
	 * @param string $userId the name of the user for security reasons
84
	 * @throws BusinessLayerException if the entity does not exist or more than one entity exists
85
	 * @phpstan-return EntityType
86
	 */
87
	public function find(int $id, string $userId) : Entity {
88
		try {
89
			return $this->mapper->find($id, $userId);
90
		} catch (DoesNotExistException $ex) {
91
			throw new BusinessLayerException($ex->getMessage());
92
		} catch (MultipleObjectsReturnedException $ex) {
93
			throw new BusinessLayerException($ex->getMessage());
94
		}
95
	}
96
97
	/**
98
	 * Finds an entity by id, or returns an empty entity instance if the requested one is not found
99
	 * @param int $id the id of the entity
100
	 * @param string $userId the name of the user for security reasons
101
	 * @phpstan-return EntityType
102
	 */
103
	public function findOrDefault(int $id, string $userId) : Entity {
104
		try {
105
			return $this->find($id, $userId);
106
		} catch (BusinessLayerException $ex) {
107
			return $this->mapper->createEntity();
108
		}
109
	}
110
111
	/**
112
	 * Find all entities matching the given IDs.
113
	 * Specifying the user is optional; if omitted, the caller should make sure that
114
	 * user's data is not leaked to unauthorized users.
115
	 * @param integer[] $ids  IDs of the entities to be found
116
	 * @param string|null $userId
117
	 * @param bool $preserveOrder If true, then the result will be in the same order as @a $ids
118
	 * @return Entity[]
119
	 * @phpstan-return EntityType[]
120
	 */
121
	public function findById(array $ids, string $userId=null, bool $preserveOrder=false) : array {
122
		$entities = [];
123
		if (\count($ids) > 0) {
124
			// don't use more than 999 SQL args in one query since that may be a problem for SQLite
125
			$idChunks = \array_chunk($ids, 998);
126
			foreach ($idChunks as $idChunk) {
127
				$entities = \array_merge($entities, $this->mapper->findById($idChunk, $userId));
128
			}
129
		}
130
131
		if ($preserveOrder) {
132
			$lut = Util::createIdLookupTable($entities);
133
			$result = [];
134
			foreach ($ids as $id) {
135
				$result[] = $lut[$id];
136
			}
137
		} else {
138
			$result = $entities;
139
		}
140
141
		return $result;
142
	}
143
144
	/**
145
	 * Finds all entities
146
	 * @param string $userId the name of the user
147
	 * @param integer $sortBy sort order of the result set
148
	 * @param integer|null $limit
149
	 * @param integer|null $offset
150
	 * @param string|null $createdMin Optional minimum `created` timestamp.
151
	 * @param string|null $createdMax Optional maximum `created` timestamp.
152
	 * @param string|null $updatedMin Optional minimum `updated` timestamp.
153
	 * @param string|null $updatedMax Optional maximum `updated` timestamp.
154
	 * @return Entity[]
155
	 * @phpstan-return EntityType[]
156
	 */
157
	public function findAll(
158
			string $userId, int $sortBy=SortBy::None, ?int $limit=null, ?int $offset=null,
159
			?string $createdMin=null, ?string $createdMax=null, ?string $updatedMin=null, ?string $updatedMax=null) : array {
160
		return $this->mapper->findAll($userId, $sortBy, $limit, $offset, $createdMin, $createdMax, $updatedMin, $updatedMax);
161
	}
162
163
	/**
164
	 * Return all entities with name matching the search criteria
165
	 * @param string|null $createdMin Optional minimum `created` timestamp.
166
	 * @param string|null $createdMax Optional maximum `created` timestamp.
167
	 * @param string|null $updatedMin Optional minimum `updated` timestamp.
168
	 * @param string|null $updatedMax Optional maximum `updated` timestamp.
169
	 * @return Entity[]
170
	 * @phpstan-return EntityType[]
171
	 */
172
	public function findAllByName(
173
			?string $name, string $userId, int $matchMode=MatchMode::Exact, ?int $limit=null, ?int $offset=null,
174
			?string $createdMin=null, ?string $createdMax=null, ?string $updatedMin=null, ?string $updatedMax=null) : array {
175
		if ($name !== null) {
176
			$name = \trim($name);
177
		}
178
		return $this->mapper->findAllByName($name, $userId, $matchMode, $limit, $offset, $createdMin, $createdMax, $updatedMin, $updatedMax);
179
	}
180
181
	/**
182
	 * Find all starred entities
183
	 * @return Entity[]
184
	 * @phpstan-return EntityType[]
185
	 */
186
	public function findAllStarred(string $userId, ?int $limit=null, ?int $offset=null) : array {
187
		return $this->mapper->findAllStarred($userId, $limit, $offset);
188
	}
189
190
	/**
191
	 * Find all entities with user-given rating 1-5
192
	 * @return Entity[]
193
	 * @phpstan-return EntityType[]
194
	 */
195
	public function findAllRated(string $userId, ?int $limit=null, ?int $offset=null) : array {
196
		return $this->mapper->findAllRated($userId, $limit, $offset);
197
	}
198
199
	/**
200
	 * Find all entities matching multiple criteria, as needed for the Ampache API method `advanced_search`
201
	 * @param string $conjunction Operator to use between the rules, either 'and' or 'or'
202
	 * @param array $rules Array of arrays: [['rule' => string, 'operator' => string, 'input' => string], ...]
203
	 * 				Here, 'rule' has dozens of possible values depending on the business layer in question,
204
	 * 				(see https://ampache.org/api/api-advanced-search#available-search-rules, alias names not supported here),
205
	 * 				'operator' is one of 
206
	 * 				['contain', 'notcontain', 'start', 'end', 'is', 'isnot', '>=', '<=', '=', '!=', '>', '<', 'true', 'false', 'equal', 'ne', 'limit'],
207
	 * 				'input' is the right side value of the 'operator' (disregarded for the operators 'true' and 'false')
208
	 * @return Entity[]
209
	 * @phpstan-return EntityType[]
210
	 */
211
	public function findAllAdvanced(string $conjunction, array $rules, string $userId, ?int $limit=null, ?int $offset=null) : array {
212
		if ($conjunction !== 'and' && $conjunction !== 'or') {
213
			throw new BusinessLayerException("Bad conjunction '$conjunction'");
214
		}
215
		try {
216
			return $this->mapper->findAllAdvanced($conjunction, $rules, $userId, $limit, $offset);
217
		} catch (\Exception $e) {
218
			// catch everything as many kinds of DB exceptions are possible on various cloud versions
219
			throw new BusinessLayerException($e->getMessage());
220
		}
221
	}
222
223
	/**
224
	 * Find IDs of all user's entities of this kind
225
	 * @return int[]
226
	 */
227
	public function findAllIds(string $userId) : array {
228
		return $this->mapper->findAllIds($userId);
229
	}
230
231
	/**
232
	 * Find IDs of all users owning any entities of this business layer
233
	 * @return string[]
234
	 */
235
	public function findAllUsers() : array {
236
		return $this->mapper->findAllUsers();
237
	}
238
239
	/**
240
	 * Set the given entities as "starred" on this date
241
	 * @param int[] $ids
242
	 * @param string $userId
243
	 * @return int number of modified entities
244
	 */
245
	public function setStarred(array $ids, string $userId) : int {
246
		if (\count($ids) > 0) {
247
			return $this->mapper->setStarredDate(new \DateTime(), $ids, $userId);
248
		} else {
249
			return 0;
250
		}
251
	}
252
253
	/**
254
	 * Remove the "starred" status of the given entities
255
	 * @param integer[] $ids
256
	 * @param string $userId
257
	 * @return int number of modified entities
258
	 */
259
	public function unsetStarred(array $ids, string $userId) : int {
260
		if (\count($ids) > 0) {
261
			return $this->mapper->setStarredDate(null, $ids, $userId);
262
		} else {
263
			return 0;
264
		}
265
	}
266
267
	/**
268
	 * Tests if entity with given ID and user ID exists in the database
269
	 * @param int $id
270
	 * @param string $userId
271
	 * @return bool
272
	 */
273
	public function exists(int $id, string $userId) : bool {
274
		return $this->mapper->exists($id, $userId);
275
	}
276
277
	/**
278
	 * Get the number of entities
279
	 * @param string $userId
280
	 */
281
	public function count(string $userId) : int {
282
		return $this->mapper->count($userId);
283
	}
284
285
	/**
286
	 * Get the timestamp of the latest insert operation on the entity type in question
287
	 */
288
	public function latestInsertTime(string $userId) : \DateTime {
289
		return $this->mapper->latestInsertTime($userId) ?? new \DateTime('1970-01-01');
290
	}
291
292
	/**
293
	 * Get the timestamp of the latest update operation on the entity type in question
294
	 */
295
	public function latestUpdateTime(string $userId) : \DateTime {
296
		return $this->mapper->latestUpdateTime($userId) ?? new \DateTime('1970-01-01');
297
	}
298
}
299