Passed
Pull Request — master (#1078)
by Pauli
05:55 queued 02:38
created

BaseMapper::selectUserEntities()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 8
rs 10
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, "ORDER BY LOWER($nameCol)");
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
				"ORDER BY LOWER(`{$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

155
				"ORDER BY LOWER(`{/** @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...
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 matching multiple criteria, as needed for the Ampache API method `advanced_search`
164
	 * @param string $conjunction Operator to use between the rules, either 'and' or 'or'
165
	 * @param array $rules Array of arrays: [['rule' => string, 'operator' => string, 'input' => string], ...]
166
	 * 				Here, 'rule' has dozens of possible values depending on the business layer in question
167
	 * 				(see https://ampache.org/api/api-advanced-search#available-search-rules, alias names not supported here),
168
	 * 				'operator' is one of 
169
	 * 				['contain', 'notcontain', 'start', 'end', 'is', 'isnot', '>=', '<=', '=', '!=', '>', '<', 'true', 'false', 'equal', 'ne', 'limit'],
170
	 * 				'input' is the right side value of the 'operator' (disregarded for the operators 'true' and 'false')
171
	 * @return Entity[]
172
	 * @phpstan-return EntityType[]
173
	 */
174
	public function findAllAdvanced(string $conjunction, array $rules, string $userId, ?int $limit=null, ?int $offset=null) : array {
175
		$sqlConditions = [];
176
		$sqlParams = [$userId];
177
178
		foreach ($rules as $rule) {
179
			list('op' => $sqlOp, 'param' => $param) = $this->advFormatSqlOperator($rule['operator'], $rule['input'], $userId);
180
			$cond = $this->advFormatSqlCondition($rule['rule'], $sqlOp);
181
			$sqlConditions[] = $cond;
182
			// On some conditions, the parameter may need to be repeated several times
183
			$paramCount = \substr_count($cond, '?');
184
			for ($i = 0; $i < $paramCount; ++$i) {
185
				$sqlParams[] = $param;
186
			}
187
		}
188
		$sqlConditions = \implode(" $conjunction ", $sqlConditions);
189
190
		$sql = $this->selectUserEntities($sqlConditions, "ORDER BY LOWER(`{$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

190
		$sql = $this->selectUserEntities($sqlConditions, "ORDER BY LOWER(`{/** @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...
191
		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

191
		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...
192
	}
193
194
	/**
195
	 * Find IDs of all user's entities of this kind
196
	 * @return int[]
197
	 */
198
	public function findAllIds(string $userId) : array {
199
		$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

199
		$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...
200
		$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

200
		$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...
201
202
		return \array_map('intval', $result->fetchAll(\PDO::FETCH_COLUMN));
203
	}
204
205
	/**
206
	 * Find IDs of all users owning any entities of this mapper
207
	 * @return string[]
208
	 */
209
	public function findAllUsers() : array {
210
		$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

210
		$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...
211
		$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

211
		$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...
212
213
		return $result->fetchAll(\PDO::FETCH_COLUMN);
214
	}
215
216
	/**
217
	 * Delete all entities with given IDs without specifying the user
218
	 * @param integer[] $ids  IDs of the entities to be deleted
219
	 */
220
	public function deleteById(array $ids) : void {
221
		$count = \count($ids);
222
		if ($count === 0) {
223
			return;
224
		}
225
		$this->deleteByCond('`id` IN ' . $this->questionMarks($count), $ids);
226
	}
227
228
	/**
229
	 * Delete all entities matching the given SQL condition
230
	 * @param string $condition SQL 'WHERE' condition (without the keyword 'WHERE')
231
	 * @param array $params SQL parameters for the condition
232
	 */
233
	protected function deleteByCond(string $condition, array $params) : void {
234
		$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

234
		$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...
235
		$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

235
		/** @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...
236
	}
237
238
	/**
239
	 * Delete all entities of the given user
240
	 */
241
	public function deleteAll(string $userId) : void {
242
		$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

242
		$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...
243
		$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

243
		/** @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...
244
	}
245
246
	/**
247
	 * Tests if entity with given ID and user ID exists in the database
248
	 */
249
	public function exists(int $id, string $userId) : bool {
250
		$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

250
		$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...
251
		$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

251
		$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...
252
		return $result->rowCount() > 0;
253
	}
254
255
	/**
256
	 * Count all entities of a user
257
	 */
258
	public function count(string $userId) : int {
259
		$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

259
		$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...
260
		$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

260
		$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...
261
		$row = $result->fetch();
262
		return \intval($row['count']);
263
	}
264
265
	/**
266
	 * {@inheritDoc}
267
	 * @see CompatibleMapper::insert()
268
	 * @phpstan-param EntityType $entity
269
	 * @phpstan-return EntityType
270
	 */
271
	public function insert(\OCP\AppFramework\Db\Entity $entity) : \OCP\AppFramework\Db\Entity {
272
		$now = new \DateTime();
273
		$nowStr = $now->format(self::SQL_DATE_FORMAT);
274
		$entity->setCreated($nowStr);
275
		$entity->setUpdated($nowStr);
276
277
		try {
278
			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

278
			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...
279
		} catch (\Doctrine\DBAL\Exception\UniqueConstraintViolationException $e) {
280
			throw new UniqueConstraintViolationException($e->getMessage(), $e->getCode(), $e);
281
		} catch (\OCP\DB\Exception $e) {
282
			// Nextcloud 21+
283
			if ($e->getReason() == \OCP\DB\Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
284
				throw new UniqueConstraintViolationException($e->getMessage(), $e->getCode(), $e);
285
			} else {
286
				throw $e;
287
			}
288
		}
289
	}
290
291
	/**
292
	 * {@inheritDoc}
293
	 * @see CompatibleMapper::update()
294
	 * @phpstan-param EntityType $entity
295
	 * @phpstan-return EntityType
296
	 */
297
	public function update(\OCP\AppFramework\Db\Entity $entity) : \OCP\AppFramework\Db\Entity {
298
		$now = new \DateTime();
299
		$entity->setUpdated($now->format(self::SQL_DATE_FORMAT));
300
		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

300
		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...
301
	}
302
303
	/**
304
	 * Insert an entity, or if an entity with the same identity already exists,
305
	 * update the existing entity.
306
	 * Note: The functions insertOrUpate and updateOrInsert get the exactly same thing done. The only difference is
307
	 * that the former is optimized for cases where the entity doens't exist and the latter for cases where it does exist.
308
	 * @return Entity The inserted or updated entity, containing also the id field
309
	 * @phpstan-param EntityType $entity
310
	 * @phpstan-return EntityType
311
	 */
312
	public function insertOrUpdate(Entity $entity) : Entity {
313
		try {
314
			return $this->insert($entity);
315
		} catch (UniqueConstraintViolationException $ex) {
316
			$existingEntity = $this->findUniqueEntity($entity);
317
			$entity->setId($existingEntity->getId());
318
			$entity->setCreated($existingEntity->getCreated());
319
			return $this->update($entity);
320
		}
321
	}
322
323
	/**
324
	 * Update an entity whose unique constraint fields match the given entity. If such entity is not found,
325
	 * a new entity is inserted.
326
	 * Note: The functions insertOrUpate and updateOrInsert get the exactly same thing done. The only difference is
327
	 * that the former is optimized for cases where the entity doens't exist and the latter for cases where it does exist.
328
	 * @return Entity The inserted or updated entity, containing also the id field
329
	 * @phpstan-param EntityType $entity
330
	 * @phpstan-return EntityType
331
	 */
332
	public function updateOrInsert(Entity $entity) : Entity {
333
		try {
334
			$existingEntity = $this->findUniqueEntity($entity);
335
			$entity->setId($existingEntity->getId());
336
			return $this->update($entity);
337
		} catch (DoesNotExistException $ex) {
338
			try {
339
				return $this->insert($entity);
340
			} catch (UniqueConstraintViolationException $ex) {
341
				// the conflicting entry didn't exist an eyeblink ago but now it does
342
				// => this is essentially a concurrent update and it is anyway non-deterministic, which
343
				//    update happens last; cancel this update
344
				return $this->findUniqueEntity($entity);
345
			}
346
		}
347
	}
348
349
	/**
350
	 * Set the "starred" column of the given entities
351
	 * @param \DateTime|null $date
352
	 * @param integer[] $ids
353
	 * @param string $userId
354
	 * @return int number of modified entities
355
	 */
356
	public function setStarredDate(?\DateTime $date, array $ids, string $userId) : int {
357
		$count = \count($ids);
358
		if (!empty($date)) {
359
			$date = $date->format(self::SQL_DATE_FORMAT);
360
		}
361
362
		$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

362
		$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...
363
				WHERE `id` IN {$this->questionMarks($count)} AND `user_id` = ?";
364
		$params = \array_merge([$date], $ids, [$userId]);
365
		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

365
		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...
366
	}
367
368
	public function latestInsertTime(string $userId) : ?\DateTime {
369
		$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

369
		$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...
370
		$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

370
		$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...
371
		$createdTime = $result->fetch(\PDO::FETCH_COLUMN);
372
373
		return ($createdTime === null) ? null : new \DateTime($createdTime);
374
	}
375
376
	public function latestUpdateTime(string $userId) : ?\DateTime {
377
		$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

377
		$sql = "SELECT MAX(`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`updated`) 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...
378
		$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

378
		$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...
379
		$createdTime = $result->fetch(\PDO::FETCH_COLUMN);
380
381
		return ($createdTime === null) ? null : new \DateTime($createdTime);
382
	}
383
384
	/**
385
	 * helper creating a string like '(?,?,?)' with the specified number of elements
386
	 */
387
	protected function questionMarks(int $count) : string {
388
		$questionMarks = [];
389
		for ($i = 0; $i < $count; $i++) {
390
			$questionMarks[] = '?';
391
		}
392
		return '(' . \implode(',', $questionMarks) . ')';
393
	}
394
395
	/**
396
	 * Build a SQL SELECT statement which selects all entities of the given user,
397
	 * and optionally applies other conditions, too.
398
	 * This is built upon `selectEntities` which may be overridden by the derived class.
399
	 * @param string|null $condition Optional extra condition. This will get automatically
400
	 *                               prefixed with ' AND ', so don't include that.
401
	 * @param string|null $extension Any extension (e.g. ORDER BY, LIMIT) to be added after
402
	 *                               the conditions in the SQL statement
403
	 */
404
	protected function selectUserEntities(string $condition=null, string $extension=null) : string {
405
		$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

405
		$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...
406
407
		if (!empty($condition)) {
408
			$allConditions .= " AND ($condition)";
409
		}
410
411
		return $this->selectEntities($allConditions, $extension);
412
	}
413
414
	/**
415
	 * Build a SQL SELECT statement which selects all entities matching the given condition.
416
	 * The derived class may override this if necessary.
417
	 * @param string $condition This will get automatically prefixed with ' WHERE '
418
	 * @param string|null $extension Any extension (e.g. ORDER BY, LIMIT) to be added after
419
	 *                               the conditions in the SQL statement
420
	 */
421
	protected function selectEntities(string $condition, string $extension=null) : string {
422
		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

422
		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...
423
	}
424
425
	/**
426
	 * @return array with two values: The SQL condition as string and the SQL parameters as string[]
427
	 */
428
	protected function formatTimestampConditions(?string $createdMin, ?string $createdMax, ?string $updatedMin, ?string $updatedMax) : array {
429
		$conditions = [];
430
		$params = [];
431
432
		if (!empty($createdMin)) {
433
			$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

433
			$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...
434
			$params[] = $createdMin;
435
		}
436
437
		if (!empty($createdMax)) {
438
			$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

438
			$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...
439
			$params[] = $createdMax;
440
		}
441
442
		if (!empty($updatedMin)) {
443
			$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

443
			$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...
444
			$params[] = $updatedMin;
445
		}
446
447
		if (!empty($updatedMax)) {
448
			$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

448
			$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...
449
			$params[] = $updatedMax;
450
		}
451
452
		return [\implode(' AND ', $conditions), $params];
453
	}
454
455
	/**
456
	 * Convert given sorting condition to an SQL clause. Derived class may overide this if necessary.
457
	 * @param int $sortBy One of the constants defined in the class SortBy
458
	 */
459
	protected function formatSortingClause(int $sortBy, bool $invertSort = false) : ?string {
460
		if ($sortBy == SortBy::Name) {
461
			$dir = $invertSort ? 'DESC' : 'ASC';
462
			return "ORDER BY LOWER(`{$this->getTableName()}`.`{$this->nameColumn}`) $dir";
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

462
			return "ORDER BY LOWER(`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`{$this->nameColumn}`) $dir";

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...
463
		} elseif ($sortBy == SortBy::Newest) {
464
			$dir = $invertSort ? 'ASC' : 'DESC';
465
			return "ORDER BY `{$this->getTableName()}`.`id` $dir"; // abuse the fact that IDs are ever-incrementing values
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

465
			return "ORDER BY `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`id` $dir"; // abuse the fact that IDs are ever-incrementing values

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...
466
		} else {
467
			return null;
468
		}
469
	}
470
471
	protected static function prepareSubstringSearchPattern(string $input) : string {
472
		// possibly multiparted query enclosed in quotation marks is handled as a single substring,
473
		// while the default interpretation of multipart string is that each of the parts can be found
474
		// separately as substring in the given order
475
		if (Util::startsWith($input, '"') && Util::endsWith($input, '"')) {
476
			// remove the quotation
477
			$pattern = \substr($input, 1, -1);
478
		} else {
479
			// split to parts by whitespace
480
			$parts = \preg_split('/\s+/', $input, -1, PREG_SPLIT_NO_EMPTY);
481
			// glue the parts back together with a wildcard charater
482
			$pattern = \implode('%', $parts);
483
		}
484
		return "%$pattern%";
485
	}
486
487
	/**
488
	 * Format SQL operator and parameter matching the given advanced search operator.
489
	 * @return array like ['op' => string, 'param' => string]
490
	 */
491
	protected function advFormatSqlOperator(string $ruleOperator, string $ruleInput, string $userId) {
492
		switch ($ruleOperator) {
493
			case 'contain':		return ['op' => 'LIKE',						'param' => "%$ruleInput%"];
494
			case 'notcontain':	return ['op' => 'NOT LIKE',					'param' => "%$ruleInput%"];
495
			case 'start':		return ['op' => 'LIKE',						'param' => "$ruleInput%"];
496
			case 'end':			return ['op' => 'LIKE',						'param' => "%$ruleInput"];
497
			case 'is':			return ['op' => '=',						'param' => "$ruleInput"];
498
			case 'isnot':		return ['op' => '!=',						'param' => "$ruleInput"];
499
			case 'sounds':		return ['op' => 'SOUNDS LIKE',				'param' => $ruleInput]; // MySQL-specific syntax
500
			case 'notsounds':	return ['op' => 'NOT SOUNDS LIKE',			'param' => $ruleInput]; // MySQL-specific syntax
501
			case 'regexp':		return ['op' => 'REGEXP',					'param' => $ruleInput]; // MySQL-specific syntax
502
			case 'notregexp':	return ['op' => 'NOT REGEXP',				'param' => $ruleInput]; // MySQL-specific syntax
503
			case 'true':		return ['op' => 'IS NOT NULL',				'param' => null];
504
			case 'false':		return ['op' => 'IS NULL',					'param' => null];
505
			case 'equal':		return ['op' => '',							'param' => $ruleInput];
506
			case 'ne':			return ['op' => 'NOT',						'param' => $ruleInput];
507
			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
508
			default:			return ['op' => $ruleOperator,				'param' => $ruleInput]; // all numerical operators fall here
509
		}
510
	}
511
512
	/**
513
	 * Format SQL condition matching the given advanced search rule and SQL operator.
514
	 * Derived classes should override this to provide support for table-specific rules.
515
	 */
516
	protected function advFormatSqlCondition(string $rule, string $sqlOp) : string {
517
		$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

517
		$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...
518
		$nameCol = $this->nameColumn;
519
520
		switch ($rule) {
521
			case 'title':			return "LOWER(`$table`.`$nameCol`) $sqlOp LOWER(?)";
522
			case 'my_flagged':		return "`$table`.`starred` $sqlOp";
523
			case 'favorite':		return "(LOWER(`$table`.`$nameCol`) $sqlOp LOWER(?) AND `$table`.`starred` IS NOT NULL)"; // title search among flagged
524
			case 'added':			return "`$table`.`created` $sqlOp ?";
525
			case 'updated':			return "`$table`.`updated` $sqlOp ?";
526
			case 'mbid':			return "`$table`.`mbid` $sqlOp ?";
527
			case 'recent_added':	return "`$table`.`id` IN (SELECT * FROM (SELECT `id` FROM `$table` WHERE `user_id` = ? ORDER BY `created` DESC LIMIT $sqlOp) mysqlhack)";
528
			case 'recent_updated':	return "`$table`.`id` IN (SELECT * FROM (SELECT `id` FROM `$table` WHERE `user_id` = ? ORDER BY `updated` DESC LIMIT $sqlOp) mysqlhack)";
529
			default:				throw new \DomainException("Rule '$rule' not supported on this entity type");
530
		}
531
	}
532
533
	/**
534
	 * Find an entity which has the same identity as the supplied entity.
535
	 * How the identity of the entity is defined, depends on the derived concrete class.
536
	 * @phpstan-param EntityType $entity
537
	 * @phpstan-return EntityType
538
	 */
539
	abstract protected function findUniqueEntity(Entity $entity) : Entity;
540
}
541