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

BaseMapper::formatSortingClause()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 17
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 15
nc 8
nop 2
dl 0
loc 17
rs 8.4444
c 0
b 0
f 0
1
<?php declare(strict_types=1);
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 - 2023
11
 */
12
13
namespace OCA\Music\Db;
14
15
use OCP\AppFramework\Db\DoesNotExistException;
16
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
17
use OCP\IDBConnection;
18
19
use OCA\Music\AppFramework\Db\CompatibleMapper;
20
use OCA\Music\AppFramework\Db\UniqueConstraintViolationException;
21
use OCA\Music\Utility\Util;
22
23
/**
24
 * Common base class for data access classes of the Music app
25
 * @phpstan-template EntityType of Entity
26
 * @phpstan-method EntityType findEntity(string $sql, array $params)
27
 * @phpstan-method EntityType[] findEntities(string $sql, array $params, ?int $limit=null, ?int $offset=null)
28
 */
29
abstract class BaseMapper extends CompatibleMapper {
0 ignored issues
show
Deprecated Code introduced by
The class OCA\Music\AppFramework\Db\OldNextcloudMapper 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

29
abstract class BaseMapper extends /** @scrutinizer ignore-deprecated */ CompatibleMapper {
Loading history...
30
	const SQL_DATE_FORMAT = 'Y-m-d H:i:s.v';
31
32
	protected $nameColumn;
33
	/** @phpstan-var class-string<EntityType> $entityClass */
34
	protected $entityClass;
35
36
	/**
37
	 * @phpstan-param class-string<EntityType> $entityClass
38
	 */
39
	public function __construct(IDBConnection $db, string $tableName, string $entityClass, string $nameColumn) {
40
		parent::__construct($db, $tableName, $entityClass);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...udMapper::__construct() 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

40
		/** @scrutinizer ignore-deprecated */ parent::__construct($db, $tableName, $entityClass);

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...
41
		$this->nameColumn = $nameColumn;
42
		// eclipse the base class property to help phpstan
43
		$this->entityClass = $entityClass;
44
	}
45
46
	/**
47
	 * Create an empty object of the entity class bound to this mapper
48
	 * @phpstan-return EntityType
49
	 */
50
	public function createEntity() : Entity {
51
		return new $this->entityClass();
52
	}
53
54
	/**
55
	 * Find a single entity by id and user_id
56
	 * @throws DoesNotExistException if the entity does not exist
57
	 * @throws MultipleObjectsReturnedException if more than one entity exists
58
	 * @phpstan-return EntityType
59
	 */
60
	public function find(int $id, string $userId) : Entity {
61
		$sql = $this->selectUserEntities("`{$this->getTableName()}`.`id` = ?");
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

61
		$sql = $this->selectUserEntities("`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`id` = ?");

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...
62
		return $this->findEntity($sql, [$userId, $id]);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->findEntity...l, array($userId, $id)) returns the type OCP\AppFramework\Db\Entity which includes types incompatible with the type-hinted return OCA\Music\Db\Entity.
Loading history...
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...oudMapper::findEntity() 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

62
		return /** @scrutinizer ignore-deprecated */ $this->findEntity($sql, [$userId, $id]);

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...
63
	}
64
65
	/**
66
	 * Find all entities matching the given IDs. Specifying the owning user is optional.
67
	 * @param integer[] $ids  IDs of the entities to be found
68
	 * @param string|null $userId
69
	 * @return Entity[]
70
	 * @phpstan-return EntityType[]
71
	 */
72
	public function findById(array $ids, string $userId=null) : array {
73
		$count = \count($ids);
74
		$condition = "`{$this->getTableName()}`.`id` IN ". $this->questionMarks($count);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

74
		$condition = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`id` IN ". $this->questionMarks($count);

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...
75
76
		if (empty($userId)) {
77
			$sql = $this->selectEntities($condition);
78
		} else {
79
			$sql = $this->selectUserEntities($condition);
80
			$ids = \array_merge([$userId], $ids);
81
		}
82
83
		return $this->findEntities($sql, $ids);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::findEntities() 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

83
		return /** @scrutinizer ignore-deprecated */ $this->findEntities($sql, $ids);

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...
84
	}
85
86
	/**
87
	 * Find all user's entities
88
	 * @param string|null $createdMin Optional minimum `created` timestamp.
89
	 * @param string|null $createdMax Optional maximum `created` timestamp.
90
	 * @param string|null $updatedMin Optional minimum `updated` timestamp.
91
	 * @param string|null $updatedMax Optional maximum `updated` timestamp.
92
	 * @return Entity[]
93
	 * @phpstan-return EntityType[]
94
	 */
95
	public function findAll(string $userId, int $sortBy=SortBy::None, int $limit=null, int $offset=null,
96
							?string $createdMin=null, ?string $createdMax=null, ?string $updatedMin=null, ?string $updatedMax=null) : array {
97
		$sorting = $this->formatSortingClause($sortBy);
98
		[$condition, $params] = $this->formatTimestampConditions($createdMin, $createdMax, $updatedMin, $updatedMax);
99
		$sql = $this->selectUserEntities($condition, $sorting);
100
		\array_unshift($params, $userId);
101
		return $this->findEntities($sql, $params, $limit, $offset);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::findEntities() 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

101
		return /** @scrutinizer ignore-deprecated */ $this->findEntities($sql, $params, $limit, $offset);

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...
102
	}
103
104
	/**
105
	 * Find all user's entities matching the given name
106
	 * @param string|null $createdMin Optional minimum `created` timestamp.
107
	 * @param string|null $createdMax Optional maximum `created` timestamp.
108
	 * @param string|null $updatedMin Optional minimum `updated` timestamp.
109
	 * @param string|null $updatedMax Optional maximum `updated` timestamp.
110
	 * @return Entity[]
111
	 * @phpstan-return EntityType[]
112
	 */
113
	public function findAllByName(
114
		?string $name, string $userId, int $matchMode=MatchMode::Exact, int $limit=null, int $offset=null,
115
		?string $createdMin=null, ?string $createdMax=null, ?string $updatedMin=null, ?string $updatedMax=null) : array {
116
117
		$params = [$userId];
118
		$nameCol = "`{$this->getTableName()}`.`{$this->nameColumn}`";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

118
		$nameCol = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`{$this->nameColumn}`";

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...
119
		if ($name === null) {
120
			$condition = "$nameCol IS NULL";
121
		} else {
122
			if ($matchMode === MatchMode::Exact) {
123
				$condition = "LOWER($nameCol) = LOWER(?)";
124
			} else {
125
				$condition = "LOWER($nameCol) LIKE LOWER(?)";
126
			}
127
			if ($matchMode === MatchMode::Substring) {
128
				$params[] = self::prepareSubstringSearchPattern($name);
129
			} else {
130
				$params[] = $name;
131
			}
132
		}
133
134
		[$timestampConds, $timestampParams] = $this->formatTimestampConditions($createdMin, $createdMax, $updatedMin, $updatedMax);
135
		if (!empty($timestampConds)) {
136
			$condition .= ' AND ' . $timestampConds;
137
			$params = \array_merge($params, $timestampParams);
138
		}
139
140
		$sql = $this->selectUserEntities($condition, $this->formatSortingClause(SortBy::Name));
141
142
		return $this->findEntities($sql, $params, $limit, $offset);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::findEntities() 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

142
		return /** @scrutinizer ignore-deprecated */ $this->findEntities($sql, $params, $limit, $offset);

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...
143
	}
144
145
	/**
146
	 * Find all user's starred entities. It is safe to call this also on entity types
147
	 * not supporting starring in which case an empty array will be returned.
148
	 * @return Entity[]
149
	 * @phpstan-return EntityType[]
150
	 */
151
	public function findAllStarred(string $userId, int $limit=null, int $offset=null) : array {
152
		if (\property_exists($this->entityClass, 'starred')) {
153
			$sql = $this->selectUserEntities(
154
				"`{$this->getTableName()}`.`starred` IS NOT NULL",
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

154
				"`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`starred` IS NOT NULL",

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...
155
				$this->formatSortingClause(SortBy::Name));
156
			return $this->findEntities($sql, [$userId], $limit, $offset);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::findEntities() 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

156
			return /** @scrutinizer ignore-deprecated */ $this->findEntities($sql, [$userId], $limit, $offset);

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...
157
		} else {
158
			return [];
159
		}
160
	}
161
162
	/**
163
	 * Find all entities with user-given rating 1-5
164
	 * @return Entity[]
165
	 * @phpstan-return EntityType[]
166
	 */
167
	public function findAllRated(string $userId, int $limit=null, int $offset=null) : array {
168
		if (\property_exists($this->entityClass, 'rating')) {
169
			$sql = $this->selectUserEntities(
170
				"`{$this->getTableName()}`.`rating` > 0",
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

170
				"`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`rating` > 0",

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...
171
				$this->formatSortingClause(SortBy::Rating));
172
			return $this->findEntities($sql, [$userId], $limit, $offset);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::findEntities() 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

172
			return /** @scrutinizer ignore-deprecated */ $this->findEntities($sql, [$userId], $limit, $offset);

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...
173
		} else {
174
			return [];
175
		}
176
	}
177
178
	/**
179
	 * Find all entities matching multiple criteria, as needed for the Ampache API method `advanced_search`
180
	 * @param string $conjunction Operator to use between the rules, either 'and' or 'or'
181
	 * @param array $rules Array of arrays: [['rule' => string, 'operator' => string, 'input' => string], ...]
182
	 * 				Here, 'rule' has dozens of possible values depending on the business layer in question
183
	 * 				(see https://ampache.org/api/api-advanced-search#available-search-rules, alias names not supported here),
184
	 * 				'operator' is one of 
185
	 * 				['contain', 'notcontain', 'start', 'end', 'is', 'isnot', '>=', '<=', '=', '!=', '>', '<', 'true', 'false', 'equal', 'ne', 'limit'],
186
	 * 				'input' is the right side value of the 'operator' (disregarded for the operators 'true' and 'false')
187
	 * @return Entity[]
188
	 * @phpstan-return EntityType[]
189
	 */
190
	public function findAllAdvanced(string $conjunction, array $rules, string $userId, ?int $limit=null, ?int $offset=null) : array {
191
		$sqlConditions = [];
192
		$sqlParams = [$userId];
193
194
		foreach ($rules as $rule) {
195
			list('op' => $sqlOp, 'param' => $param) = $this->advFormatSqlOperator($rule['operator'], $rule['input'], $userId);
196
			$cond = $this->advFormatSqlCondition($rule['rule'], $sqlOp);
197
			$sqlConditions[] = $cond;
198
			// On some conditions, the parameter may need to be repeated several times
199
			$paramCount = \substr_count($cond, '?');
200
			for ($i = 0; $i < $paramCount; ++$i) {
201
				$sqlParams[] = $param;
202
			}
203
		}
204
		$sqlConditions = \implode(" $conjunction ", $sqlConditions);
205
206
		$sql = $this->selectUserEntities($sqlConditions, $this->formatSortingClause(SortBy::Name));
207
		return $this->findEntities($sql, $sqlParams, $limit, $offset);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::findEntities() 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

207
		return /** @scrutinizer ignore-deprecated */ $this->findEntities($sql, $sqlParams, $limit, $offset);

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...
208
	}
209
210
	/**
211
	 * Find IDs of all user's entities of this kind
212
	 * @return int[]
213
	 */
214
	public function findAllIds(string $userId) : array {
215
		$sql = "SELECT `id` FROM `{$this->getTableName()}` WHERE `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

215
		$sql = "SELECT `id` FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE `user_id` = ?";

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...
216
		$result = $this->execute($sql, [$userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() 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

216
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql, [$userId]);

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...
217
218
		return \array_map('intval', $result->fetchAll(\PDO::FETCH_COLUMN));
219
	}
220
221
	/**
222
	 * Find IDs of all users owning any entities of this mapper
223
	 * @return string[]
224
	 */
225
	public function findAllUsers() : array {
226
		$sql = "SELECT DISTINCT(`user_id`) FROM `{$this->getTableName()}`";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

226
		$sql = "SELECT DISTINCT(`user_id`) FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`";

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...
227
		$result = $this->execute($sql);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() 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

227
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql);

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...
228
229
		return $result->fetchAll(\PDO::FETCH_COLUMN);
230
	}
231
232
	/**
233
	 * Delete all entities with given IDs without specifying the user
234
	 * @param integer[] $ids  IDs of the entities to be deleted
235
	 */
236
	public function deleteById(array $ids) : void {
237
		$count = \count($ids);
238
		if ($count === 0) {
239
			return;
240
		}
241
		$this->deleteByCond('`id` IN ' . $this->questionMarks($count), $ids);
242
	}
243
244
	/**
245
	 * Delete all entities matching the given SQL condition
246
	 * @param string $condition SQL 'WHERE' condition (without the keyword 'WHERE')
247
	 * @param array $params SQL parameters for the condition
248
	 */
249
	protected function deleteByCond(string $condition, array $params) : void {
250
		$sql = "DELETE FROM `{$this->getTableName()}` WHERE ". $condition;
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

250
		$sql = "DELETE FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE ". $condition;

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...
251
		$this->execute($sql, $params);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() 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

251
		/** @scrutinizer ignore-deprecated */ $this->execute($sql, $params);

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...
252
	}
253
254
	/**
255
	 * Delete all entities of the given user
256
	 */
257
	public function deleteAll(string $userId) : void {
258
		$sql = "DELETE FROM `{$this->getTableName()}` WHERE `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

258
		$sql = "DELETE FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE `user_id` = ?";

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...
259
		$this->execute($sql, [$userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() 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

259
		/** @scrutinizer ignore-deprecated */ $this->execute($sql, [$userId]);

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...
260
	}
261
262
	/**
263
	 * Tests if entity with given ID and user ID exists in the database
264
	 */
265
	public function exists(int $id, string $userId) : bool {
266
		$sql = "SELECT 1 FROM `{$this->getTableName()}` WHERE `id` = ? AND `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

266
		$sql = "SELECT 1 FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE `id` = ? AND `user_id` = ?";

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...
267
		$result = $this->execute($sql, [$id, $userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() 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

267
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql, [$id, $userId]);

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...
268
		return $result->rowCount() > 0;
269
	}
270
271
	/**
272
	 * Count all entities of a user
273
	 */
274
	public function count(string $userId) : int {
275
		$sql = "SELECT COUNT(*) AS count FROM `{$this->getTableName()}` WHERE `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

275
		$sql = "SELECT COUNT(*) AS count FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE `user_id` = ?";

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...
276
		$result = $this->execute($sql, [$userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() 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

276
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql, [$userId]);

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...
277
		$row = $result->fetch();
278
		return \intval($row['count']);
279
	}
280
281
	/**
282
	 * {@inheritDoc}
283
	 * @see CompatibleMapper::insert()
284
	 * @phpstan-param EntityType $entity
285
	 * @phpstan-return EntityType
286
	 */
287
	public function insert(\OCP\AppFramework\Db\Entity $entity) : \OCP\AppFramework\Db\Entity {
288
		$now = new \DateTime();
289
		$nowStr = $now->format(self::SQL_DATE_FORMAT);
290
		$entity->setCreated($nowStr);
291
		$entity->setUpdated($nowStr);
292
293
		try {
294
			return parent::insert($entity); // @phpstan-ignore-line: no way to tell phpstan that the parent uses the template type
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...xtcloudMapper::insert() 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

294
			return /** @scrutinizer ignore-deprecated */ parent::insert($entity); // @phpstan-ignore-line: no way to tell phpstan that the parent uses the template type

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...
295
		} catch (\Doctrine\DBAL\Exception\UniqueConstraintViolationException $e) {
296
			throw new UniqueConstraintViolationException($e->getMessage(), $e->getCode(), $e);
297
		} catch (\OCP\DB\Exception $e) {
298
			// Nextcloud 21+
299
			if ($e->getReason() == \OCP\DB\Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
300
				throw new UniqueConstraintViolationException($e->getMessage(), $e->getCode(), $e);
301
			} else {
302
				throw $e;
303
			}
304
		}
305
	}
306
307
	/**
308
	 * {@inheritDoc}
309
	 * @see CompatibleMapper::update()
310
	 * @phpstan-param EntityType $entity
311
	 * @phpstan-return EntityType
312
	 */
313
	public function update(\OCP\AppFramework\Db\Entity $entity) : \OCP\AppFramework\Db\Entity {
314
		$now = new \DateTime();
315
		$entity->setUpdated($now->format(self::SQL_DATE_FORMAT));
316
		return parent::update($entity); // @phpstan-ignore-line: no way to tell phpstan that the parent uses the template type
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...xtcloudMapper::update() 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

316
		return /** @scrutinizer ignore-deprecated */ parent::update($entity); // @phpstan-ignore-line: no way to tell phpstan that the parent uses the template type

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...
317
	}
318
319
	/**
320
	 * Insert an entity, or if an entity with the same identity already exists,
321
	 * update the existing entity.
322
	 * Note: The functions insertOrUpate and updateOrInsert get the exactly same thing done. The only difference is
323
	 * that the former is optimized for cases where the entity doens't exist and the latter for cases where it does exist.
324
	 * @return Entity The inserted or updated entity, containing also the id field
325
	 * @phpstan-param EntityType $entity
326
	 * @phpstan-return EntityType
327
	 */
328
	public function insertOrUpdate(Entity $entity) : Entity {
329
		try {
330
			return $this->insert($entity);
331
		} catch (UniqueConstraintViolationException $ex) {
332
			$existingEntity = $this->findUniqueEntity($entity);
333
			$entity->setId($existingEntity->getId());
334
			$entity->setCreated($existingEntity->getCreated());
335
			return $this->update($entity);
336
		}
337
	}
338
339
	/**
340
	 * Update an entity whose unique constraint fields match the given entity. If such entity is not found,
341
	 * a new entity is inserted.
342
	 * Note: The functions insertOrUpate and updateOrInsert get the exactly same thing done. The only difference is
343
	 * that the former is optimized for cases where the entity doens't exist and the latter for cases where it does exist.
344
	 * @return Entity The inserted or updated entity, containing also the id field
345
	 * @phpstan-param EntityType $entity
346
	 * @phpstan-return EntityType
347
	 */
348
	public function updateOrInsert(Entity $entity) : Entity {
349
		try {
350
			$existingEntity = $this->findUniqueEntity($entity);
351
			$entity->setId($existingEntity->getId());
352
			return $this->update($entity);
353
		} catch (DoesNotExistException $ex) {
354
			try {
355
				return $this->insert($entity);
356
			} catch (UniqueConstraintViolationException $ex) {
357
				// the conflicting entry didn't exist an eyeblink ago but now it does
358
				// => this is essentially a concurrent update and it is anyway non-deterministic, which
359
				//    update happens last; cancel this update
360
				return $this->findUniqueEntity($entity);
361
			}
362
		}
363
	}
364
365
	/**
366
	 * Set the "starred" column of the given entities
367
	 * @param \DateTime|null $date
368
	 * @param integer[] $ids
369
	 * @param string $userId
370
	 * @return int number of modified entities
371
	 */
372
	public function setStarredDate(?\DateTime $date, array $ids, string $userId) : int {
373
		$count = \count($ids);
374
		if (!empty($date)) {
375
			$date = $date->format(self::SQL_DATE_FORMAT);
376
		}
377
378
		$sql = "UPDATE `{$this->getTableName()}` SET `starred` = ?
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

378
		$sql = "UPDATE `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` SET `starred` = ?

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...
379
				WHERE `id` IN {$this->questionMarks($count)} AND `user_id` = ?";
380
		$params = \array_merge([$date], $ids, [$userId]);
381
		return $this->execute($sql, $params)->rowCount();
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() 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

381
		return /** @scrutinizer ignore-deprecated */ $this->execute($sql, $params)->rowCount();

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...
382
	}
383
384
	public function latestInsertTime(string $userId) : ?\DateTime {
385
		$sql = "SELECT MAX(`{$this->getTableName()}`.`created`) FROM `{$this->getTableName()}` WHERE `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

385
		$sql = "SELECT MAX(`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`created`) FROM `{$this->getTableName()}` WHERE `user_id` = ?";

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...
386
		$result = $this->execute($sql, [$userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() 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

386
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql, [$userId]);

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...
387
		$createdTime = $result->fetch(\PDO::FETCH_COLUMN);
388
389
		return ($createdTime === null) ? null : new \DateTime($createdTime);
390
	}
391
392
	public function latestUpdateTime(string $userId) : ?\DateTime {
393
		$sql = "SELECT MAX(`{$this->getTableName()}`.`updated`) FROM `{$this->getTableName()}` WHERE `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

393
		$sql = "SELECT MAX(`{$this->getTableName()}`.`updated`) FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE `user_id` = ?";

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...
394
		$result = $this->execute($sql, [$userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() 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

394
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql, [$userId]);

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...
395
		$createdTime = $result->fetch(\PDO::FETCH_COLUMN);
396
397
		return ($createdTime === null) ? null : new \DateTime($createdTime);
398
	}
399
400
	/**
401
	 * helper creating a string like '(?,?,?)' with the specified number of elements
402
	 */
403
	protected function questionMarks(int $count) : string {
404
		$questionMarks = [];
405
		for ($i = 0; $i < $count; $i++) {
406
			$questionMarks[] = '?';
407
		}
408
		return '(' . \implode(',', $questionMarks) . ')';
409
	}
410
411
	/**
412
	 * Build a SQL SELECT statement which selects all entities of the given user,
413
	 * and optionally applies other conditions, too.
414
	 * This is built upon `selectEntities` which may be overridden by the derived class.
415
	 * @param string|null $condition Optional extra condition. This will get automatically
416
	 *                               prefixed with ' AND ', so don't include that.
417
	 * @param string|null $extension Any extension (e.g. ORDER BY, LIMIT) to be added after
418
	 *                               the conditions in the SQL statement
419
	 */
420
	protected function selectUserEntities(string $condition=null, string $extension=null) : string {
421
		$allConditions = "`{$this->getTableName()}`.`user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

421
		$allConditions = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`user_id` = ?";

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...
422
423
		if (!empty($condition)) {
424
			$allConditions .= " AND ($condition)";
425
		}
426
427
		return $this->selectEntities($allConditions, $extension);
428
	}
429
430
	/**
431
	 * Build a SQL SELECT statement which selects all entities matching the given condition.
432
	 * The derived class may override this if necessary.
433
	 * @param string $condition This will get automatically prefixed with ' WHERE '
434
	 * @param string|null $extension Any extension (e.g. ORDER BY, LIMIT) to be added after
435
	 *                               the conditions in the SQL statement
436
	 */
437
	protected function selectEntities(string $condition, string $extension=null) : string {
438
		return "SELECT * FROM `{$this->getTableName()}` WHERE $condition $extension ";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

438
		return "SELECT * FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE $condition $extension ";

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...
439
	}
440
441
	/**
442
	 * @return array with two values: The SQL condition as string and the SQL parameters as string[]
443
	 */
444
	protected function formatTimestampConditions(?string $createdMin, ?string $createdMax, ?string $updatedMin, ?string $updatedMax) : array {
445
		$conditions = [];
446
		$params = [];
447
448
		if (!empty($createdMin)) {
449
			$conditions[] = "`{$this->getTableName()}`.`created` >= ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

449
			$conditions[] = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`created` >= ?";

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...
450
			$params[] = $createdMin;
451
		}
452
453
		if (!empty($createdMax)) {
454
			$conditions[] = "`{$this->getTableName()}`.`created` <= ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

454
			$conditions[] = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`created` <= ?";

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...
455
			$params[] = $createdMax;
456
		}
457
458
		if (!empty($updatedMin)) {
459
			$conditions[] = "`{$this->getTableName()}`.`updated` >= ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

459
			$conditions[] = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`updated` >= ?";

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...
460
			$params[] = $updatedMin;
461
		}
462
463
		if (!empty($updatedMax)) {
464
			$conditions[] = "`{$this->getTableName()}`.`updated` <= ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

464
			$conditions[] = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`updated` <= ?";

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...
465
			$params[] = $updatedMax;
466
		}
467
468
		return [\implode(' AND ', $conditions), $params];
469
	}
470
471
	/**
472
	 * Convert given sorting condition to an SQL clause. Derived class may overide this if necessary.
473
	 * @param int $sortBy One of the constants defined in the class SortBy
474
	 */
475
	protected function formatSortingClause(int $sortBy, bool $invertSort = false) : ?string {
476
		$table = $this->getTableName();
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

476
		$table = /** @scrutinizer ignore-deprecated */ $this->getTableName();

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...
477
		if ($sortBy == SortBy::Name) {
478
			$dir = $invertSort ? 'DESC' : 'ASC';
479
			return "ORDER BY LOWER(`$table`.`{$this->nameColumn}`) $dir";
480
		} elseif ($sortBy == SortBy::Newest) {
481
			$dir = $invertSort ? 'ASC' : 'DESC';
482
			return "ORDER BY `$table`.`id` $dir"; // abuse the fact that IDs are ever-incrementing values
483
		} elseif ($sortBy == SortBy::Rating) {
484
			if (\property_exists($this->entityClass, 'rating')) {
485
				$dir = $invertSort ? 'ASC' : 'DESC';
486
				return "ORDER BY `$table`.`rating` $dir";
487
			} else {
488
				return null;
489
			}
490
		} else {
491
			return null;
492
		}
493
	}
494
495
	protected static function prepareSubstringSearchPattern(string $input) : string {
496
		// possibly multiparted query enclosed in quotation marks is handled as a single substring,
497
		// while the default interpretation of multipart string is that each of the parts can be found
498
		// separately as substring in the given order
499
		if (Util::startsWith($input, '"') && Util::endsWith($input, '"')) {
500
			// remove the quotation
501
			$pattern = \substr($input, 1, -1);
502
		} else {
503
			// split to parts by whitespace
504
			$parts = \preg_split('/\s+/', $input, -1, PREG_SPLIT_NO_EMPTY);
505
			// glue the parts back together with a wildcard charater
506
			$pattern = \implode('%', $parts);
507
		}
508
		return "%$pattern%";
509
	}
510
511
	/**
512
	 * Format SQL operator and parameter matching the given advanced search operator.
513
	 * @return array like ['op' => string, 'param' => string]
514
	 */
515
	protected function advFormatSqlOperator(string $ruleOperator, string $ruleInput, string $userId) {
516
		switch ($ruleOperator) {
517
			case 'contain':		return ['op' => 'LIKE',						'param' => "%$ruleInput%"];
518
			case 'notcontain':	return ['op' => 'NOT LIKE',					'param' => "%$ruleInput%"];
519
			case 'start':		return ['op' => 'LIKE',						'param' => "$ruleInput%"];
520
			case 'end':			return ['op' => 'LIKE',						'param' => "%$ruleInput"];
521
			case 'is':			return ['op' => '=',						'param' => "$ruleInput"];
522
			case 'isnot':		return ['op' => '!=',						'param' => "$ruleInput"];
523
			case 'sounds':		return ['op' => 'SOUNDS LIKE',				'param' => $ruleInput]; // MySQL-specific syntax
524
			case 'notsounds':	return ['op' => 'NOT SOUNDS LIKE',			'param' => $ruleInput]; // MySQL-specific syntax
525
			case 'regexp':		return ['op' => 'REGEXP',					'param' => $ruleInput]; // MySQL-specific syntax
526
			case 'notregexp':	return ['op' => 'NOT REGEXP',				'param' => $ruleInput]; // MySQL-specific syntax
527
			case 'true':		return ['op' => 'IS NOT NULL',				'param' => null];
528
			case 'false':		return ['op' => 'IS NULL',					'param' => null];
529
			case 'equal':		return ['op' => '',							'param' => $ruleInput];
530
			case 'ne':			return ['op' => 'NOT',						'param' => $ruleInput];
531
			case 'limit':		return ['op' => (string)(int)$ruleInput,	'param' => $userId];	// this is a bit hacky, userId needs to be passed as an SQL param while simple sanitation suffices for the limit
532
			default:			return ['op' => $ruleOperator,				'param' => $ruleInput]; // all numerical operators fall here
533
		}
534
	}
535
536
	/**
537
	 * Format SQL condition matching the given advanced search rule and SQL operator.
538
	 * Derived classes should override this to provide support for table-specific rules.
539
	 */
540
	protected function advFormatSqlCondition(string $rule, string $sqlOp) : string {
541
		$table = $this->getTableName();
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() 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

541
		$table = /** @scrutinizer ignore-deprecated */ $this->getTableName();

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...
542
		$nameCol = $this->nameColumn;
543
544
		switch ($rule) {
545
			case 'title':			return "LOWER(`$table`.`$nameCol`) $sqlOp LOWER(?)";
546
			case 'my_flagged':		return "`$table`.`starred` $sqlOp";
547
			case 'favorite':		return "(LOWER(`$table`.`$nameCol`) $sqlOp LOWER(?) AND `$table`.`starred` IS NOT NULL)"; // title search among flagged
548
			case 'myrating':		// fall throuhg, we provide no access to other people's data
549
			case 'rating':			return "`$table`.`rating` $sqlOp ?";
550
			case 'added':			return "`$table`.`created` $sqlOp ?";
551
			case 'updated':			return "`$table`.`updated` $sqlOp ?";
552
			case 'mbid':			return "`$table`.`mbid` $sqlOp ?";
553
			case 'recent_added':	return "`$table`.`id` IN (SELECT * FROM (SELECT `id` FROM `$table` WHERE `user_id` = ? ORDER BY `created` DESC LIMIT $sqlOp) mysqlhack)";
554
			case 'recent_updated':	return "`$table`.`id` IN (SELECT * FROM (SELECT `id` FROM `$table` WHERE `user_id` = ? ORDER BY `updated` DESC LIMIT $sqlOp) mysqlhack)";
555
			default:				throw new \DomainException("Rule '$rule' not supported on this entity type");
556
		}
557
	}
558
559
	/**
560
	 * Find an entity which has the same identity as the supplied entity.
561
	 * How the identity of the entity is defined, depends on the derived concrete class.
562
	 * @phpstan-param EntityType $entity
563
	 * @phpstan-return EntityType
564
	 */
565
	abstract protected function findUniqueEntity(Entity $entity) : Entity;
566
}
567