Passed
Push — feature/909_Ampache_API_improv... ( f93b1c...7380bc )
by Pauli
02:41
created

TrackMapper::selectEntities()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 13
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 Morris Jobke <[email protected]>
10
 * @author Pauli Järvinen <[email protected]>
11
 * @copyright Morris Jobke 2013, 2014
12
 * @copyright Pauli Järvinen 2016 - 2023
13
 */
14
15
namespace OCA\Music\Db;
16
17
use OCP\IDBConnection;
18
19
/**
20
 * @phpstan-extends BaseMapper<Track>
21
 */
22
class TrackMapper extends BaseMapper {
23
	public function __construct(IDBConnection $db) {
24
		parent::__construct($db, 'music_tracks', Track::class, 'title');
25
	}
26
27
	/**
28
	 * Override the base implementation to include data from multiple tables
29
	 *
30
	 * {@inheritdoc}
31
	 * @see BaseMapper::selectEntities()
32
	 */
33
	protected function selectEntities(string $condition, string $extension=null) : string {
34
		return "SELECT `*PREFIX*music_tracks`.*, `file`.`name` AS `filename`, `file`.`size`, `file`.`mtime` AS `file_mod_time`,
35
						`album`.`name` AS `album_name`, `artist`.`name` AS `artist_name`, `genre`.`name` AS `genre_name`
36
				FROM `*PREFIX*music_tracks`
37
				INNER JOIN `*PREFIX*filecache` `file`
38
				ON `*PREFIX*music_tracks`.`file_id` = `file`.`fileid`
39
				INNER JOIN `*PREFIX*music_albums` `album`
40
				ON `*PREFIX*music_tracks`.`album_id` = `album`.`id`
41
				INNER JOIN `*PREFIX*music_artists` `artist`
42
				ON `*PREFIX*music_tracks`.`artist_id` = `artist`.`id`
43
				LEFT JOIN `*PREFIX*music_genres` `genre`
44
				ON `*PREFIX*music_tracks`.`genre_id` = `genre`.`id`
45
				WHERE $condition $extension";
46
	}
47
48
	/**
49
	 * Overridden from the base implementation to add support for sorting by artist, play_count, and last_played.
50
	 *
51
	 * {@inheritdoc}
52
	 * @see BaseMapper::formatSortingClause()
53
	 */
54
	protected function formatSortingClause(int $sortBy, bool $invertSort = false) : ?string {
55
		$dir = $invertSort ? 'DESC' : 'ASC';
56
		switch ($sortBy) {
57
			case SortBy::Parent:
58
				// Note: the alternative form "LOWER(`artist_name`) wouldn't work on PostgreSQL, see https://github.com/owncloud/music/issues/1046 for a similar case
59
				return "ORDER BY LOWER(`artist`.`name`) $dir, LOWER(`title`) $dir";
60
			case SortBy::PlayCount:
61
				return "ORDER BY LOWER(`play_count`) $dir";
62
			case SortBy::LastPlayed:
63
				return "ORDER BY LOWER(`last_played`) $dir";
64
			default:
65
				return parent::formatSortingClause($sortBy, $invertSort);
66
		}
67
	}
68
69
	/**
70
	 * Overridden from the base implementation to provide support for table-specific rules
71
	 *
72
	 * {@inheritdoc}
73
	 * @see BaseMapper::advFormatSqlCondition()
74
	 */
75
	protected function advFormatSqlCondition(string $rule, string $sqlOp) : string {
76
		switch ($rule) {
77
			case 'album':			return "`album_id` IN (SELECT `id` from `*PREFIX*music_albums` `al` WHERE LOWER(`al`.`name`) $sqlOp LOWER(?))";
78
			case 'artist':			return "`artist_id` IN (SELECT `id` from `*PREFIX*music_artists` `ar` WHERE LOWER(`ar`.`name`) $sqlOp LOWER(?))";
79
			case 'album_artist':	return "`album_id` IN (SELECT `al`.`id` from `*PREFIX*music_albums` `al` JOIN `*PREFIX*music_artists` `ar` ON `al`.`album_artist_id` = `ar`.`id` WHERE LOWER(`ar`.`name`) $sqlOp LOWER(?))";
80
			case 'track':			return "`number` $sqlOp ?";
81
			case 'year':			return "`year` $sqlOp ?";
82
			case 'favorite_album':	return "`album_id` IN (SELECT `id` from `*PREFIX*music_albums` `al` WHERE LOWER(`al`.`name`) $sqlOp LOWER(?) AND `al`.`starred` IS NOT NULL)";
83
			case 'favorite_artist':	return "`artist_id` IN (SELECT `id` from `*PREFIX*music_artists` `ar` WHERE LOWER(`ar`.`name`) $sqlOp LOWER(?) AND `ar`.`starred` IS NOT NULL)";
84
			case 'played_times':	return "`play_count` $sqlOp ?";
85
			case 'last_play':		return "`last_played` $sqlOp ?";
86
			case 'played':			// fall through, we give no access to other people's data
87
			case 'myplayed':		return "`last_played` $sqlOp"; // operator "IS NULL" or "IS NOT NULL"
88
			//case 'myplayedalbum':
89
			//case 'myplayedartist':
90
			case 'time':			return "`length` $sqlOp ?";
91
			case 'genre':			// fall through
92
			case 'song_genre':		return "`genre_id` IN (SELECT `id` from `*PREFIX*music_genres` `ge` WHERE LOWER(`ge`.`name`) $sqlOp LOWER(?))";
93
			//case 'albumgenre':
94
			//case 'artistgenre':
95
			case 'no_genre':		return ($sqlOp == 'IS NOT NULL') ? '`genre`.`name` = ""' : '`genre`.`name` != ""';
96
			//case 'playlist':
97
			//case 'playlist_name':	TODO: pattern to match against playlist track_ids somethign like: ('%|' || CONVERT(varchar(10), `*PREFIX*music_tracks`.`id`) || '|%')
98
			//case 'recent_played':
99
			//case 'recent_added':
100
			//case 'recent_updated':
101
			case 'file':			return "LOWER(`file`.`name`) $sqlOp LOWER(?)";
102
			default:				return parent::advFormatSqlCondition($rule, $sqlOp);
103
		}
104
	}
105
106
	/**
107
	 * Returns all tracks of the given artist (both album and track artists are considered)
108
	 * @return Track[]
109
	 */
110
	public function findAllByArtist(int $artistId, string $userId, ?int $limit=null, ?int $offset=null) : array {
111
		$sql = $this->selectUserEntities(
112
				'`artist_id` = ? OR `album_id` IN (SELECT `id` from `*PREFIX*music_albums` WHERE `album_artist_id` = ?) ',
113
				'ORDER BY LOWER(`title`)');
114
		$params = [$userId, $artistId, $artistId];
115
		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

115
		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...
116
	}
117
118
	/**
119
	 * @return Track[]
120
	 */
121
	public function findAllByAlbum(int $albumId, string $userId, ?int $artistId=null, ?int $limit=null, ?int $offset=null) : array {
122
		$condition = '`album_id` = ?';
123
		$params = [$userId, $albumId];
124
125
		if ($artistId !== null) {
126
			$condition .= ' AND `artist_id` = ? ';
127
			$params[] = $artistId;
128
		}
129
130
		$sql = $this->selectUserEntities($condition,
131
				'ORDER BY `*PREFIX*music_tracks`.`disk`, `number`, LOWER(`title`)');
132
		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

132
		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...
133
	}
134
135
	/**
136
	 * @return Track[]
137
	 */
138
	public function findAllByFolder(int $folderId, string $userId, ?int $limit=null, ?int $offset=null) : array {
139
		$sql = $this->selectUserEntities('`file`.`parent` = ?', 'ORDER BY LOWER(`title`)');
140
		$params = [$userId, $folderId];
141
		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

141
		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...
142
	}
143
144
	/**
145
	 * @return Track[]
146
	 */
147
	public function findAllByGenre(int $genreId, string $userId, ?int $limit=null, ?int $offset=null) : array {
148
		$sql = $this->selectUserEntities('`genre_id` = ?', 'ORDER BY LOWER(`title`)');
149
		$params = [$userId, $genreId];
150
		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

150
		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...
151
	}
152
153
	/**
154
	 * @param string $userId
155
	 * @return int[]
156
	 */
157
	public function findAllFileIds(string $userId) : array {
158
		$sql = 'SELECT `file_id` FROM `*PREFIX*music_tracks` WHERE `user_id` = ?';
159
		$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

159
		$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...
160
161
		return \array_map(function ($i) {
162
			return (int)$i['file_id'];
163
		}, $result->fetchAll());
164
	}
165
166
	/**
167
	 * Find a track of user matching a file ID
168
	 * @throws \OCP\AppFramework\Db\DoesNotExistException if not found
169
	 */
170
	public function findByFileId(int $fileId, string $userId) : Track {
171
		$sql = $this->selectUserEntities('`file_id` = ?');
172
		$params = [$userId, $fileId];
173
		return $this->findEntity($sql, $params);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->findEntity($sql, $params) returns the type OCP\AppFramework\Db\Entity which includes types incompatible with the type-hinted return OCA\Music\Db\Track.
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

173
		return /** @scrutinizer ignore-deprecated */ $this->findEntity($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...
174
	}
175
176
	/**
177
	 * Find tracks of user with multiple file IDs
178
	 * @param integer[] $fileIds
179
	 * @param string[] $userIds
180
	 * @return Track[]
181
	 */
182
	public function findByFileIds(array $fileIds, array $userIds) : array {
183
		$sql = $this->selectEntities(
184
				'`*PREFIX*music_tracks`.`user_id` IN ' . $this->questionMarks(\count($userIds)) .
185
				' AND `file_id` IN '. $this->questionMarks(\count($fileIds)));
186
		$params = \array_merge($userIds, $fileIds);
187
		return $this->findEntities($sql, $params);
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

187
		return /** @scrutinizer ignore-deprecated */ $this->findEntities($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...
188
	}
189
190
	/**
191
	 * Finds tracks of all users matching one or multiple file IDs
192
	 * @param integer[] $fileIds
193
	 * @return Track[]
194
	 */
195
	public function findAllByFileIds(array $fileIds) : array {
196
		$sql = $this->selectEntities('`file_id` IN '.
197
				$this->questionMarks(\count($fileIds)));
198
		return $this->findEntities($sql, $fileIds);
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

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

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...
199
	}
200
201
	public function countByArtist(int $artistId) : int {
202
		$sql = 'SELECT COUNT(*) AS `count` FROM `*PREFIX*music_tracks` WHERE `artist_id` = ?';
203
		$result = $this->execute($sql, [$artistId]);
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

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

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...
204
		$row = $result->fetch();
205
		return (int)$row['count'];
206
	}
207
208
	public function countByAlbum(int $albumId) : int {
209
		$sql = 'SELECT COUNT(*) AS `count` FROM `*PREFIX*music_tracks` WHERE `album_id` = ?';
210
		$result = $this->execute($sql, [$albumId]);
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

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

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
		$row = $result->fetch();
212
		return (int)$row['count'];
213
	}
214
215
	/**
216
	 * @return integer Duration in seconds
217
	 */
218
	public function totalDurationOfAlbum(int $albumId) : int {
219
		$sql = 'SELECT SUM(`length`) AS `duration` FROM `*PREFIX*music_tracks` WHERE `album_id` = ?';
220
		$result = $this->execute($sql, [$albumId]);
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

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

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...
221
		$row = $result->fetch();
222
		return (int)$row['duration'];
223
	}
224
225
	/**
226
	 * @return integer Duration in seconds
227
	 */
228
	public function totalDurationByArtist(int $artistId) : int {
229
		$sql = 'SELECT SUM(`length`) AS `duration` FROM `*PREFIX*music_tracks` WHERE `artist_id` = ?';
230
		$result = $this->execute($sql, [$artistId]);
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

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

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...
231
		$row = $result->fetch();
232
		return (int)$row['duration'];
233
	}
234
235
	/**
236
	 * Get durations of the given tracks.
237
	 * @param integer[] $trackIds
238
	 * @return array {int => int} where keys are track IDs and values are corresponding durations
239
	 */
240
	public function getDurations(array $trackIds) : array {
241
		$result = [];
242
243
		if (!empty($trackIds)) {
244
			$sql = 'SELECT `id`, `length` FROM `*PREFIX*music_tracks` WHERE `id` IN ' .
245
						$this->questionMarks(\count($trackIds));
246
			$rows = $this->execute($sql, $trackIds)->fetchAll();
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

246
			$rows = /** @scrutinizer ignore-deprecated */ $this->execute($sql, $trackIds)->fetchAll();

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...
247
			foreach ($rows as $row) {
248
				$result[$row['id']] = (int)$row['length'];
249
			}
250
		}
251
		return $result;
252
	}
253
254
	/**
255
	 * @return Track[]
256
	 */
257
	public function findAllByNameRecursive(string $name, string $userId, ?int $limit=null, ?int $offset=null) {
258
		$condition = '( LOWER(`artist`.`name`) LIKE LOWER(?) OR
259
						LOWER(`album`.`name`) LIKE LOWER(?) OR
260
						LOWER(`title`) LIKE LOWER(?) )';
261
		$sql = $this->selectUserEntities($condition, 'ORDER BY LOWER(`title`)');
262
		$name = BaseMapper::prepareSubstringSearchPattern($name);
263
		$params = [$userId, $name, $name, $name];
264
		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

264
		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...
265
	}
266
267
	/**
268
	 * Returns all tracks specified by name and/or artist name
269
	 * @param string|null $name the name of the track
270
	 * @param string|null $artistName the name of the artist
271
	 * @param string $userId the name of the user
272
	 * @return Track[] Tracks matching the criteria
273
	 */
274
	public function findAllByNameAndArtistName(?string $name, ?string $artistName, string $userId) : array {
275
		$sqlConditions = [];
276
		$params = [$userId];
277
278
		if (!empty($name)) {
279
			$sqlConditions[] = '`title` = ?';
280
			$params[] = $name;
281
		}
282
283
		if (!empty($artistName)) {
284
			$sqlConditions[] = '`artist`.`name` = ?';
285
			$params[] = $artistName;
286
		}
287
288
		// at least one condition has to be given, otherwise return an empty set
289
		if (\count($sqlConditions) > 0) {
290
			$sql = $this->selectUserEntities(\implode(' AND ', $sqlConditions));
291
			return $this->findEntities($sql, $params);
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

291
			return /** @scrutinizer ignore-deprecated */ $this->findEntities($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...
292
		} else {
293
			return [];
294
		}
295
	}
296
297
	/**
298
	 * Returns all tracks specified by various criteria, all of which are optional
299
	 * @param int[] $genres Array of genre IDs
300
	 * @param int[] $artists Array of artist IDs
301
	 * @param int|null $fromYear Earliest release year to include
302
	 * @param int|null $toYear Latest release year to include
303
	 * @param int $sortBy Sorting rule as defined in the class SortBy
304
	 * @param string $userId the name of the user
305
	 * @return Track[] Tracks matching the criteria
306
	 */
307
	public function findAllByCriteria(
308
			array $genres, array $artists, ?int $fromYear, ?int $toYear,
309
			int $sortBy, bool $invertSort, string $userId, ?int $limit=null, ?int $offset=null) : array {
310
311
		$sqlConditions = [];
312
		$params = [$userId];
313
314
		if (!empty($genres)) {
315
			$sqlConditions[] = '`genre_id` IN ' . $this->questionMarks(\count($genres));
316
			$params = \array_merge($params, $genres);
317
		}
318
319
		if (!empty($artists)) {
320
			$sqlConditions[] = '`artist_id` IN ' . $this->questionMarks(\count($artists));
321
			$params = \array_merge($params, $artists);
322
		}
323
324
		if (!empty($fromYear)) {
325
			$sqlConditions[] = '`year` >= ?';
326
			$params[] = $fromYear;
327
		}
328
329
		if (!empty($toYear)) {
330
			$sqlConditions[] = '`year` <= ?';
331
			$params[] = $toYear;
332
		}
333
334
		$sql = $this->selectUserEntities(\implode(' AND ', $sqlConditions), $this->formatSortingClause($sortBy, $invertSort));
335
		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

335
		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...
336
	}
337
338
	/**
339
	 * Find most frequently played tracks
340
	 * @return Track[]
341
	 */
342
	public function findFrequentPlay(string $userId, ?int $limit=null, ?int $offset=null) : array {
343
		$sql = $this->selectUserEntities('`play_count` > 0', 'ORDER BY `play_count` DESC, LOWER(`title`)');
344
		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

344
		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...
345
	}
346
347
	/**
348
	 * Find most recently played tracks
349
	 * @return Track[]
350
	 */
351
	public function findRecentPlay(string $userId, ?int $limit=null, ?int $offset=null) : array {
352
		$sql = $this->selectUserEntities('`last_played` IS NOT NULL', 'ORDER BY `last_played` DESC');
353
		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

353
		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...
354
	}
355
356
	/**
357
	 * Find least recently played tracks
358
	 * @return Track[]
359
	 */
360
	public function findNotRecentPlay(string $userId, ?int $limit=null, ?int $offset=null) : array {
361
		$sql = $this->selectUserEntities(null, 'ORDER BY `last_played` ASC');
362
		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

362
		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...
363
	}
364
365
	/**
366
	 * Finds all track IDs of the user along with the parent folder ID of each track
367
	 * @return array where keys are folder IDs and values are arrays of track IDs
368
	 */
369
	public function findTrackAndFolderIds(string $userId) : array {
370
		$sql = 'SELECT `track`.`id` AS id, `file`.`name` AS `filename`, `file`.`parent` AS parent
371
				FROM `*PREFIX*music_tracks` `track`
372
				JOIN `*PREFIX*filecache` `file`
373
				ON `track`.`file_id` = `file`.`fileid`
374
				WHERE `track`.`user_id` = ?';
375
376
		$rows = $this->execute($sql, [$userId])->fetchAll();
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

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

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...
377
378
		// Sort the results according the file names. This can't be made using ORDERBY in the
379
		// SQL query because then we couldn't use the "natural order" comparison algorithm
380
		\usort($rows, function ($a, $b) {
381
			return \strnatcasecmp($a['filename'], $b['filename']);
382
		});
383
384
		// group the files to parent folder "buckets"
385
		$result = [];
386
		foreach ($rows as $row) {
387
			$result[(int)$row['parent']][] = (int)$row['id'];
388
		}
389
390
		return $result;
391
	}
392
393
	/**
394
	 * Find names and parents of the file system nodes with given IDs within the given storage
395
	 * @param int[] $nodeIds
396
	 * @param string $storageId
397
	 * @return array where keys are the node IDs and values are associative arrays
398
	 *         like { 'name' => string, 'parent' => int };
399
	 */
400
	public function findNodeNamesAndParents(array $nodeIds, string $storageId) : array {
401
		$result = [];
402
403
		if (!empty($nodeIds)) {
404
			$sql = 'SELECT `fileid`, `name`, `parent` '.
405
					'FROM `*PREFIX*filecache` `filecache` '.
406
					'JOIN `*PREFIX*storages` `storages` '.
407
					'ON `filecache`.`storage` = `storages`.`numeric_id` '.
408
					'WHERE `storages`.`id` = ? '.
409
					'AND `filecache`.`fileid` IN '. $this->questionMarks(\count($nodeIds));
410
411
			$rows = $this->execute($sql, \array_merge([$storageId], $nodeIds))->fetchAll();
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

411
			$rows = /** @scrutinizer ignore-deprecated */ $this->execute($sql, \array_merge([$storageId], $nodeIds))->fetchAll();

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...
412
413
			foreach ($rows as $row) {
414
				$result[$row['fileid']] = [
415
					'name' => $row['name'],
416
					'parent' => (int)$row['parent']
417
				];
418
			}
419
		}
420
421
		return $result;
422
	}
423
424
	/**
425
	 * Returns all genre IDs associated with the given artist
426
	 * @return int[]
427
	 */
428
	public function getGenresByArtistId(int $artistId, string $userId) : array {
429
		$sql = 'SELECT DISTINCT(`genre_id`) FROM `*PREFIX*music_tracks` WHERE
430
				`genre_id` IS NOT NULL AND `user_id` = ? AND `artist_id` = ?';
431
		$rows = $this->execute($sql, [$userId, $artistId]);
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

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

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...
432
		return $rows->fetchAll(\PDO::FETCH_COLUMN);
433
	}
434
435
	/**
436
	 * Returns all tracks IDs of the user, organized by the genre_id.
437
	 * @return array where keys are genre IDs and values are arrays of track IDs
438
	 */
439
	public function mapGenreIdsToTrackIds(string $userId) : array {
440
		$sql = 'SELECT `id`, `genre_id` FROM `*PREFIX*music_tracks`
441
				WHERE `genre_id` IS NOT NULL and `user_id` = ?';
442
		$rows = $this->execute($sql, [$userId])->fetchAll();
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

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

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...
443
444
		$result = [];
445
		foreach ($rows as $row) {
446
			$result[(int)$row['genre_id']][] = (int)$row['id'];
447
		}
448
449
		return $result;
450
	}
451
452
	/**
453
	 * Returns file IDs of the tracks which do not have genre scanned. This is not the same
454
	 * thing as unknown genre, which means that the genre has been scanned but was not found
455
	 * from the track metadata.
456
	 * @return int[]
457
	 */
458
	public function findFilesWithoutScannedGenre(string $userId) : array {
459
		$sql = 'SELECT `track`.`file_id` FROM `*PREFIX*music_tracks` `track`
460
				INNER JOIN `*PREFIX*filecache` `file`
461
				ON `track`.`file_id` = `file`.`fileid`
462
				WHERE `genre_id` IS NULL and `user_id` = ?';
463
		$rows = $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

463
		$rows = /** @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...
464
		return $rows->fetchAll(\PDO::FETCH_COLUMN);
465
	}
466
467
	/**
468
	 * Update "last played" timestamp and increment the total play count of the track.
469
	 * The DB row is updated *without* updating the `updated` column.
470
	 * @return bool true if the track was found and updated, false otherwise
471
	 */
472
	public function recordTrackPlayed(int $trackId, string $userId, \DateTime $timeOfPlay) : bool {
473
		$sql = 'UPDATE `*PREFIX*music_tracks`
474
				SET `last_played` = ?, `play_count` = `play_count` + 1
475
				WHERE `user_id` = ? AND `id` = ?';
476
		$params = [$timeOfPlay->format(BaseMapper::SQL_DATE_FORMAT), $userId, $trackId];
477
		$result = $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

477
		$result = /** @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...
478
		return ($result->rowCount() > 0);
479
	}
480
481
	/**
482
	 * @see \OCA\Music\Db\BaseMapper::findUniqueEntity()
483
	 * @param Track $track
484
	 * @return Track
485
	 */
486
	protected function findUniqueEntity(Entity $track) : Entity {
487
		return $this->findByFileId($track->getFileId(), $track->getUserId());
0 ignored issues
show
Bug introduced by
It seems like $track->getFileId() can also be of type null; however, parameter $fileId of OCA\Music\Db\TrackMapper::findByFileId() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

487
		return $this->findByFileId(/** @scrutinizer ignore-type */ $track->getFileId(), $track->getUserId());
Loading history...
Bug introduced by
The method getFileId() does not exist on OCA\Music\Db\Entity. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

487
		return $this->findByFileId($track->/** @scrutinizer ignore-call */ getFileId(), $track->getUserId());
Loading history...
488
	}
489
}
490