| Total Complexity | 83 |
| Total Lines | 496 |
| Duplicated Lines | 0 % |
| Changes | 17 | ||
| Bugs | 0 | Features | 0 |
Complex classes like TrackMapper often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use TrackMapper, and based on these observations, apply Extract Interface, too.
| 1 | <?php declare(strict_types=1); |
||
| 23 | class TrackMapper extends BaseMapper { |
||
| 24 | public function __construct(IDBConnection $db, IConfig $config) { |
||
| 25 | parent::__construct($db, $config, 'music_tracks', Track::class, 'title', 'album_id'); |
||
| 26 | } |
||
| 27 | |||
| 28 | /** |
||
| 29 | * Override the base implementation to include data from multiple tables |
||
| 30 | * |
||
| 31 | * {@inheritdoc} |
||
| 32 | * @see BaseMapper::selectEntities() |
||
| 33 | */ |
||
| 34 | protected function selectEntities(string $condition, string $extension=null) : string { |
||
| 35 | return "SELECT `*PREFIX*music_tracks`.*, `file`.`name` AS `filename`, `file`.`size`, `file`.`mtime` AS `file_mod_time`, |
||
| 36 | `album`.`name` AS `album_name`, `artist`.`name` AS `artist_name`, `genre`.`name` AS `genre_name` |
||
| 37 | FROM `*PREFIX*music_tracks` |
||
| 38 | INNER JOIN `*PREFIX*filecache` `file` |
||
| 39 | ON `*PREFIX*music_tracks`.`file_id` = `file`.`fileid` |
||
| 40 | INNER JOIN `*PREFIX*music_albums` `album` |
||
| 41 | ON `*PREFIX*music_tracks`.`album_id` = `album`.`id` |
||
| 42 | INNER JOIN `*PREFIX*music_artists` `artist` |
||
| 43 | ON `*PREFIX*music_tracks`.`artist_id` = `artist`.`id` |
||
| 44 | LEFT JOIN `*PREFIX*music_genres` `genre` |
||
| 45 | ON `*PREFIX*music_tracks`.`genre_id` = `genre`.`id` |
||
| 46 | WHERE $condition $extension"; |
||
| 47 | } |
||
| 48 | |||
| 49 | /** |
||
| 50 | * Overridden from the base implementation to add support for sorting by artist, play_count, and last_played. |
||
| 51 | * |
||
| 52 | * {@inheritdoc} |
||
| 53 | * @see BaseMapper::formatSortingClause() |
||
| 54 | */ |
||
| 55 | protected function formatSortingClause(int $sortBy, bool $invertSort = false) : ?string { |
||
| 56 | switch ($sortBy) { |
||
| 57 | case SortBy::Parent: |
||
| 58 | $dir = $invertSort ? 'DESC' : 'ASC'; |
||
| 59 | // Note: the alternative form "LOWER(`artist_name`) wouldn't work on PostgreSQL, see https://github.com/owncloud/music/issues/1046 for a similar case |
||
| 60 | return "ORDER BY LOWER(`artist`.`name`) $dir, LOWER(`title`) $dir"; |
||
| 61 | case SortBy::PlayCount: |
||
| 62 | $dir = $invertSort ? 'ASC' : 'DESC'; |
||
| 63 | return "ORDER BY `play_count` $dir"; |
||
| 64 | case SortBy::LastPlayed: |
||
| 65 | $dir = $invertSort ? 'ASC' : 'DESC'; |
||
| 66 | return "ORDER BY `last_played` $dir"; |
||
| 67 | default: |
||
| 68 | return parent::formatSortingClause($sortBy, $invertSort); |
||
| 69 | } |
||
| 70 | } |
||
| 71 | |||
| 72 | /** |
||
| 73 | * Returns all tracks of the given artist (both album and track artists are considered) |
||
| 74 | * @param int[] $artistIds |
||
| 75 | * @return Track[] |
||
| 76 | */ |
||
| 77 | public function findAllByArtist(array $artistIds, string $userId, ?int $limit=null, ?int $offset=null) : array { |
||
| 78 | $questionMarks = $this->questionMarks(\count($artistIds)); |
||
| 79 | $sql = $this->selectUserEntities( |
||
| 80 | "`artist_id` IN $questionMarks OR `album_id` IN (SELECT `id` from `*PREFIX*music_albums` WHERE `album_artist_id` IN $questionMarks)", |
||
| 81 | 'ORDER BY LOWER(`title`)'); |
||
| 82 | $params = \array_merge([$userId], $artistIds, $artistIds); |
||
| 83 | return $this->findEntities($sql, $params, $limit, $offset); |
||
| 84 | } |
||
| 85 | |||
| 86 | /** |
||
| 87 | * @param int[] $albumIds |
||
| 88 | * @return Track[] |
||
| 89 | */ |
||
| 90 | public function findAllByAlbum(array $albumIds, string $userId, ?int $artistId=null, ?int $limit=null, ?int $offset=null) : array { |
||
| 91 | $condition = '`album_id` IN ' . $this->questionMarks(\count($albumIds)); |
||
| 92 | $params = \array_merge([$userId], $albumIds); |
||
| 93 | |||
| 94 | if ($artistId !== null) { |
||
| 95 | $condition .= ' AND `artist_id` = ? '; |
||
| 96 | $params[] = $artistId; |
||
| 97 | } |
||
| 98 | |||
| 99 | $sql = $this->selectUserEntities($condition, |
||
| 100 | 'ORDER BY `*PREFIX*music_tracks`.`disk`, `number`, LOWER(`title`)'); |
||
| 101 | return $this->findEntities($sql, $params, $limit, $offset); |
||
| 102 | } |
||
| 103 | |||
| 104 | /** |
||
| 105 | * @return Track[] |
||
| 106 | */ |
||
| 107 | public function findAllByFolder(int $folderId, string $userId, ?int $limit=null, ?int $offset=null) : array { |
||
| 108 | $sql = $this->selectUserEntities('`file`.`parent` = ?', 'ORDER BY LOWER(`title`)'); |
||
| 109 | $params = [$userId, $folderId]; |
||
| 110 | return $this->findEntities($sql, $params, $limit, $offset); |
||
| 111 | } |
||
| 112 | |||
| 113 | /** |
||
| 114 | * @return Track[] |
||
| 115 | */ |
||
| 116 | public function findAllByGenre(int $genreId, string $userId, ?int $limit=null, ?int $offset=null) : array { |
||
| 117 | $sql = $this->selectUserEntities('`genre_id` = ?', 'ORDER BY LOWER(`title`)'); |
||
| 118 | $params = [$userId, $genreId]; |
||
| 119 | return $this->findEntities($sql, $params, $limit, $offset); |
||
| 120 | } |
||
| 121 | |||
| 122 | /** |
||
| 123 | * @param string $userId |
||
| 124 | * @return int[] |
||
| 125 | */ |
||
| 126 | public function findAllFileIds(string $userId) : array { |
||
| 127 | $sql = 'SELECT `file_id` FROM `*PREFIX*music_tracks` WHERE `user_id` = ?'; |
||
| 128 | $result = $this->execute($sql, [$userId]); |
||
| 129 | |||
| 130 | return \array_map(function ($i) { |
||
| 131 | return (int)$i['file_id']; |
||
| 132 | }, $result->fetchAll()); |
||
| 133 | } |
||
| 134 | |||
| 135 | /** |
||
| 136 | * Find a track of user matching a file ID |
||
| 137 | * @throws \OCP\AppFramework\Db\DoesNotExistException if not found |
||
| 138 | */ |
||
| 139 | public function findByFileId(int $fileId, string $userId) : Track { |
||
| 140 | $sql = $this->selectUserEntities('`file_id` = ?'); |
||
| 141 | $params = [$userId, $fileId]; |
||
| 142 | return $this->findEntity($sql, $params); |
||
|
|
|||
| 143 | } |
||
| 144 | |||
| 145 | /** |
||
| 146 | * Find tracks of user with multiple file IDs |
||
| 147 | * @param integer[] $fileIds |
||
| 148 | * @param string[] $userIds |
||
| 149 | * @return Track[] |
||
| 150 | */ |
||
| 151 | public function findByFileIds(array $fileIds, array $userIds) : array { |
||
| 152 | $sql = $this->selectEntities( |
||
| 153 | '`*PREFIX*music_tracks`.`user_id` IN ' . $this->questionMarks(\count($userIds)) . |
||
| 154 | ' AND `file_id` IN '. $this->questionMarks(\count($fileIds))); |
||
| 155 | $params = \array_merge($userIds, $fileIds); |
||
| 156 | return $this->findEntities($sql, $params); |
||
| 157 | } |
||
| 158 | |||
| 159 | /** |
||
| 160 | * Finds tracks of all users matching one or multiple file IDs |
||
| 161 | * @param integer[] $fileIds |
||
| 162 | * @return Track[] |
||
| 163 | */ |
||
| 164 | public function findAllByFileIds(array $fileIds) : array { |
||
| 165 | $sql = $this->selectEntities('`file_id` IN '. |
||
| 166 | $this->questionMarks(\count($fileIds))); |
||
| 167 | return $this->findEntities($sql, $fileIds); |
||
| 168 | } |
||
| 169 | |||
| 170 | public function countByArtist(int $artistId) : int { |
||
| 171 | $sql = 'SELECT COUNT(*) AS `count` FROM `*PREFIX*music_tracks` WHERE `artist_id` = ?'; |
||
| 172 | $result = $this->execute($sql, [$artistId]); |
||
| 173 | $row = $result->fetch(); |
||
| 174 | return (int)$row['count']; |
||
| 175 | } |
||
| 176 | |||
| 177 | public function countByAlbum(int $albumId) : int { |
||
| 178 | $sql = 'SELECT COUNT(*) AS `count` FROM `*PREFIX*music_tracks` WHERE `album_id` = ?'; |
||
| 179 | $result = $this->execute($sql, [$albumId]); |
||
| 180 | $row = $result->fetch(); |
||
| 181 | return (int)$row['count']; |
||
| 182 | } |
||
| 183 | |||
| 184 | /** |
||
| 185 | * @return integer Duration in seconds |
||
| 186 | */ |
||
| 187 | public function totalDurationOfAlbum(int $albumId) : int { |
||
| 188 | $sql = 'SELECT SUM(`length`) AS `duration` FROM `*PREFIX*music_tracks` WHERE `album_id` = ?'; |
||
| 189 | $result = $this->execute($sql, [$albumId]); |
||
| 190 | $row = $result->fetch(); |
||
| 191 | return (int)$row['duration']; |
||
| 192 | } |
||
| 193 | |||
| 194 | /** |
||
| 195 | * @return integer Duration in seconds |
||
| 196 | */ |
||
| 197 | public function totalDurationByArtist(int $artistId) : int { |
||
| 198 | $sql = 'SELECT SUM(`length`) AS `duration` FROM `*PREFIX*music_tracks` WHERE `artist_id` = ?'; |
||
| 199 | $result = $this->execute($sql, [$artistId]); |
||
| 200 | $row = $result->fetch(); |
||
| 201 | return (int)$row['duration']; |
||
| 202 | } |
||
| 203 | |||
| 204 | /** |
||
| 205 | * Get durations of the given tracks. |
||
| 206 | * @param integer[] $trackIds |
||
| 207 | * @return array {int => int} where keys are track IDs and values are corresponding durations |
||
| 208 | */ |
||
| 209 | public function getDurations(array $trackIds) : array { |
||
| 221 | } |
||
| 222 | |||
| 223 | /** |
||
| 224 | * @return Track[] |
||
| 225 | */ |
||
| 226 | public function findAllByNameRecursive(string $name, string $userId, ?int $limit=null, ?int $offset=null) { |
||
| 227 | $condition = '( LOWER(`artist`.`name`) LIKE LOWER(?) OR |
||
| 228 | LOWER(`album`.`name`) LIKE LOWER(?) OR |
||
| 229 | LOWER(`title`) LIKE LOWER(?) )'; |
||
| 230 | $sql = $this->selectUserEntities($condition, 'ORDER BY LOWER(`title`)'); |
||
| 231 | $name = BaseMapper::prepareSubstringSearchPattern($name); |
||
| 232 | $params = [$userId, $name, $name, $name]; |
||
| 233 | return $this->findEntities($sql, $params, $limit, $offset); |
||
| 234 | } |
||
| 235 | |||
| 236 | /** |
||
| 237 | * Returns all tracks specified by name and/or artist name |
||
| 238 | * @param string|null $name the name of the track |
||
| 239 | * @param string|null $artistName the name of the artist |
||
| 240 | * @param string $userId the name of the user |
||
| 241 | * @return Track[] Tracks matching the criteria |
||
| 242 | */ |
||
| 243 | public function findAllByNameAndArtistName(?string $name, ?string $artistName, string $userId) : array { |
||
| 244 | $sqlConditions = []; |
||
| 245 | $params = [$userId]; |
||
| 246 | |||
| 247 | if (!empty($name)) { |
||
| 248 | $sqlConditions[] = '`title` = ?'; |
||
| 249 | $params[] = $name; |
||
| 250 | } |
||
| 251 | |||
| 252 | if (!empty($artistName)) { |
||
| 253 | $sqlConditions[] = '`artist`.`name` = ?'; |
||
| 254 | $params[] = $artistName; |
||
| 255 | } |
||
| 256 | |||
| 257 | // at least one condition has to be given, otherwise return an empty set |
||
| 258 | if (\count($sqlConditions) > 0) { |
||
| 259 | $sql = $this->selectUserEntities(\implode(' AND ', $sqlConditions)); |
||
| 260 | return $this->findEntities($sql, $params); |
||
| 261 | } else { |
||
| 262 | return []; |
||
| 263 | } |
||
| 264 | } |
||
| 265 | |||
| 266 | /** |
||
| 267 | * Returns all tracks specified by various criteria, all of which are optional |
||
| 268 | * @param int[] $genres Array of genre IDs |
||
| 269 | * @param int[] $artists Array of artist IDs |
||
| 270 | * @param int|null $fromYear Earliest release year to include |
||
| 271 | * @param int|null $toYear Latest release year to include |
||
| 272 | * @param int $sortBy Sorting rule as defined in the class SortBy |
||
| 273 | * @param string $userId the name of the user |
||
| 274 | * @return Track[] Tracks matching the criteria |
||
| 275 | */ |
||
| 276 | public function findAllByCriteria( |
||
| 277 | array $genres, array $artists, ?int $fromYear, ?int $toYear, |
||
| 278 | int $sortBy, bool $invertSort, string $userId, ?int $limit=null, ?int $offset=null) : array { |
||
| 279 | |||
| 280 | $sqlConditions = []; |
||
| 281 | $params = [$userId]; |
||
| 282 | |||
| 283 | if (!empty($genres)) { |
||
| 284 | $sqlConditions[] = '`genre_id` IN ' . $this->questionMarks(\count($genres)); |
||
| 285 | $params = \array_merge($params, $genres); |
||
| 286 | } |
||
| 287 | |||
| 288 | if (!empty($artists)) { |
||
| 289 | $sqlConditions[] = '`artist_id` IN ' . $this->questionMarks(\count($artists)); |
||
| 290 | $params = \array_merge($params, $artists); |
||
| 291 | } |
||
| 292 | |||
| 293 | if (!empty($fromYear)) { |
||
| 294 | $sqlConditions[] = '`year` >= ?'; |
||
| 295 | $params[] = $fromYear; |
||
| 296 | } |
||
| 297 | |||
| 298 | if (!empty($toYear)) { |
||
| 299 | $sqlConditions[] = '`year` <= ?'; |
||
| 300 | $params[] = $toYear; |
||
| 301 | } |
||
| 302 | |||
| 303 | $sql = $this->selectUserEntities(\implode(' AND ', $sqlConditions), $this->formatSortingClause($sortBy, $invertSort)); |
||
| 304 | return $this->findEntities($sql, $params, $limit, $offset); |
||
| 305 | } |
||
| 306 | |||
| 307 | /** |
||
| 308 | * Find most frequently played tracks |
||
| 309 | * @return Track[] |
||
| 310 | */ |
||
| 311 | public function findFrequentPlay(string $userId, ?int $limit=null, ?int $offset=null) : array { |
||
| 312 | $sql = $this->selectUserEntities('`play_count` > 0', 'ORDER BY `play_count` DESC, LOWER(`title`)'); |
||
| 313 | return $this->findEntities($sql, [$userId], $limit, $offset); |
||
| 314 | } |
||
| 315 | |||
| 316 | /** |
||
| 317 | * Find most recently played tracks |
||
| 318 | * @return Track[] |
||
| 319 | */ |
||
| 320 | public function findRecentPlay(string $userId, ?int $limit=null, ?int $offset=null) : array { |
||
| 321 | $sql = $this->selectUserEntities('`last_played` IS NOT NULL', 'ORDER BY `last_played` DESC'); |
||
| 322 | return $this->findEntities($sql, [$userId], $limit, $offset); |
||
| 323 | } |
||
| 324 | |||
| 325 | /** |
||
| 326 | * Find least recently played tracks |
||
| 327 | * @return Track[] |
||
| 328 | */ |
||
| 329 | public function findNotRecentPlay(string $userId, ?int $limit=null, ?int $offset=null) : array { |
||
| 330 | $sql = $this->selectUserEntities(null, 'ORDER BY `last_played` ASC'); |
||
| 331 | return $this->findEntities($sql, [$userId], $limit, $offset); |
||
| 332 | } |
||
| 333 | |||
| 334 | /** |
||
| 335 | * Finds all track IDs of the user along with the parent folder ID of each track |
||
| 336 | * @return array where keys are folder IDs and values are arrays of track IDs |
||
| 337 | */ |
||
| 338 | public function findTrackAndFolderIds(string $userId) : array { |
||
| 339 | $sql = 'SELECT `track`.`id` AS id, `file`.`name` AS `filename`, `file`.`parent` AS parent |
||
| 340 | FROM `*PREFIX*music_tracks` `track` |
||
| 341 | JOIN `*PREFIX*filecache` `file` |
||
| 342 | ON `track`.`file_id` = `file`.`fileid` |
||
| 343 | WHERE `track`.`user_id` = ?'; |
||
| 344 | |||
| 345 | $rows = $this->execute($sql, [$userId])->fetchAll(); |
||
| 346 | |||
| 347 | // Sort the results according the file names. This can't be made using ORDERBY in the |
||
| 348 | // SQL query because then we couldn't use the "natural order" comparison algorithm |
||
| 349 | \usort($rows, function ($a, $b) { |
||
| 350 | return \strnatcasecmp($a['filename'], $b['filename']); |
||
| 351 | }); |
||
| 352 | |||
| 353 | // group the files to parent folder "buckets" |
||
| 354 | $result = []; |
||
| 355 | foreach ($rows as $row) { |
||
| 356 | $result[(int)$row['parent']][] = (int)$row['id']; |
||
| 357 | } |
||
| 358 | |||
| 359 | return $result; |
||
| 360 | } |
||
| 361 | |||
| 362 | /** |
||
| 363 | * Find names and parents of the file system nodes with given IDs within the given storage |
||
| 364 | * @param int[] $nodeIds |
||
| 365 | * @param string $storageId |
||
| 366 | * @return array where keys are the node IDs and values are associative arrays |
||
| 367 | * like { 'name' => string, 'parent' => int }; |
||
| 368 | */ |
||
| 369 | public function findNodeNamesAndParents(array $nodeIds, string $storageId) : array { |
||
| 370 | $result = []; |
||
| 371 | |||
| 372 | if (!empty($nodeIds)) { |
||
| 373 | $sql = 'SELECT `fileid`, `name`, `parent` '. |
||
| 374 | 'FROM `*PREFIX*filecache` `filecache` '. |
||
| 375 | 'JOIN `*PREFIX*storages` `storages` '. |
||
| 376 | 'ON `filecache`.`storage` = `storages`.`numeric_id` '. |
||
| 377 | 'WHERE `storages`.`id` = ? '. |
||
| 378 | 'AND `filecache`.`fileid` IN '. $this->questionMarks(\count($nodeIds)); |
||
| 379 | |||
| 380 | $rows = $this->execute($sql, \array_merge([$storageId], $nodeIds))->fetchAll(); |
||
| 381 | |||
| 382 | foreach ($rows as $row) { |
||
| 383 | $result[$row['fileid']] = [ |
||
| 384 | 'name' => $row['name'], |
||
| 385 | 'parent' => (int)$row['parent'] |
||
| 386 | ]; |
||
| 387 | } |
||
| 388 | } |
||
| 389 | |||
| 390 | return $result; |
||
| 391 | } |
||
| 392 | |||
| 393 | /** |
||
| 394 | * Returns all genre IDs associated with the given artist |
||
| 395 | * @return int[] |
||
| 396 | */ |
||
| 397 | public function getGenresByArtistId(int $artistId, string $userId) : array { |
||
| 398 | $sql = 'SELECT DISTINCT(`genre_id`) FROM `*PREFIX*music_tracks` WHERE |
||
| 399 | `genre_id` IS NOT NULL AND `user_id` = ? AND `artist_id` = ?'; |
||
| 400 | $rows = $this->execute($sql, [$userId, $artistId]); |
||
| 401 | return $rows->fetchAll(\PDO::FETCH_COLUMN); |
||
| 402 | } |
||
| 403 | |||
| 404 | /** |
||
| 405 | * Returns all tracks IDs of the user, organized by the genre_id. |
||
| 406 | * @return array where keys are genre IDs and values are arrays of track IDs |
||
| 407 | */ |
||
| 408 | public function mapGenreIdsToTrackIds(string $userId) : array { |
||
| 409 | $sql = 'SELECT `id`, `genre_id` FROM `*PREFIX*music_tracks` |
||
| 410 | WHERE `genre_id` IS NOT NULL and `user_id` = ?'; |
||
| 411 | $rows = $this->execute($sql, [$userId])->fetchAll(); |
||
| 412 | |||
| 413 | $result = []; |
||
| 414 | foreach ($rows as $row) { |
||
| 415 | $result[(int)$row['genre_id']][] = (int)$row['id']; |
||
| 416 | } |
||
| 417 | |||
| 418 | return $result; |
||
| 419 | } |
||
| 420 | |||
| 421 | /** |
||
| 422 | * Returns file IDs of the tracks which do not have genre scanned. This is not the same |
||
| 423 | * thing as unknown genre, which means that the genre has been scanned but was not found |
||
| 424 | * from the track metadata. |
||
| 425 | * @return int[] |
||
| 426 | */ |
||
| 427 | public function findFilesWithoutScannedGenre(string $userId) : array { |
||
| 428 | $sql = 'SELECT `track`.`file_id` FROM `*PREFIX*music_tracks` `track` |
||
| 429 | INNER JOIN `*PREFIX*filecache` `file` |
||
| 430 | ON `track`.`file_id` = `file`.`fileid` |
||
| 431 | WHERE `genre_id` IS NULL and `user_id` = ?'; |
||
| 432 | $rows = $this->execute($sql, [$userId]); |
||
| 433 | return $rows->fetchAll(\PDO::FETCH_COLUMN); |
||
| 434 | } |
||
| 435 | |||
| 436 | /** |
||
| 437 | * Update "last played" timestamp and increment the total play count of the track. |
||
| 438 | * The DB row is updated *without* updating the `updated` column. |
||
| 439 | * @return bool true if the track was found and updated, false otherwise |
||
| 440 | */ |
||
| 441 | public function recordTrackPlayed(int $trackId, string $userId, \DateTime $timeOfPlay) : bool { |
||
| 442 | $sql = 'UPDATE `*PREFIX*music_tracks` |
||
| 443 | SET `last_played` = ?, `play_count` = `play_count` + 1 |
||
| 444 | WHERE `user_id` = ? AND `id` = ?'; |
||
| 445 | $params = [$timeOfPlay->format(BaseMapper::SQL_DATE_FORMAT), $userId, $trackId]; |
||
| 446 | $result = $this->execute($sql, $params); |
||
| 447 | return ($result->rowCount() > 0); |
||
| 448 | } |
||
| 449 | |||
| 450 | /** |
||
| 451 | * Overridden from the base implementation to provide support for table-specific rules |
||
| 452 | * |
||
| 453 | * {@inheritdoc} |
||
| 454 | * @see BaseMapper::advFormatSqlCondition() |
||
| 455 | */ |
||
| 456 | protected function advFormatSqlCondition(string $rule, string $sqlOp, string $conv) : string { |
||
| 457 | // The extra subquery "mysqlhack" seen around some nested queries is needed in order for these to not be insanely slow on MySQL. |
||
| 458 | switch ($rule) { |
||
| 459 | case 'anywhere': return self::formatAdvSearchAnywhereCond($sqlOp, $conv); |
||
| 460 | case 'album': return "`album_id` IN (SELECT `id` from `*PREFIX*music_albums` `al` WHERE $conv(`al`.`name`) $sqlOp $conv(?))"; |
||
| 461 | case 'artist': return "$conv(`artist`.`name`) $sqlOp $conv(?)"; |
||
| 462 | 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 $conv(`ar`.`name`) $sqlOp $conv(?))"; |
||
| 463 | case 'track': return "`number` $sqlOp ?"; |
||
| 464 | case 'year': return "`year` $sqlOp ?"; |
||
| 465 | case 'albumrating': return "`album`.`rating` $sqlOp ?"; |
||
| 466 | case 'artistrating': return "`artist`.`rating` $sqlOp ?"; |
||
| 467 | case 'favorite_album': return "`album_id` IN (SELECT `id` from `*PREFIX*music_albums` `al` WHERE $conv(`al`.`name`) $sqlOp $conv(?) AND `al`.`starred` IS NOT NULL)"; |
||
| 468 | case 'favorite_artist': return "`artist_id` IN (SELECT `id` from `*PREFIX*music_artists` `ar` WHERE $conv(`ar`.`name`) $sqlOp $conv(?) AND `ar`.`starred` IS NOT NULL)"; |
||
| 469 | case 'played_times': return "`play_count` $sqlOp ?"; |
||
| 470 | case 'last_play': return "`last_played` $sqlOp ?"; |
||
| 471 | case 'played': // fall through, we give no access to other people's data |
||
| 472 | case 'myplayed': return "`last_played` $sqlOp"; // operator "IS NULL" or "IS NOT NULL" |
||
| 473 | case 'myplayedalbum': return "`album_id` IN (SELECT * FROM (SELECT `album_id` from `*PREFIX*music_tracks` GROUP BY `album_id` HAVING MAX(`last_played`) $sqlOp) mysqlhack)"; // operator "IS NULL" or "IS NOT NULL" |
||
| 474 | case 'myplayedartist': return "`artist_id` IN (SELECT * FROM (SELECT `artist_id` from `*PREFIX*music_tracks` GROUP BY `artist_id` HAVING MAX(`last_played`) $sqlOp) mysqlhack)"; // operator "IS NULL" or "IS NOT NULL" |
||
| 475 | case 'time': return "`length` $sqlOp ?"; |
||
| 476 | case 'bitrate': return "`bitrate` $sqlOp ?"; |
||
| 477 | case 'genre': // fall through |
||
| 478 | case 'song_genre': return "$conv(`genre`.`name`) $sqlOp $conv(?)"; |
||
| 479 | case 'album_genre': return "`album_id` IN (SELECT * FROM (SELECT `album_id` FROM `*PREFIX*music_tracks` `t` JOIN `*PREFIX*music_genres` `g` ON `t`.`genre_id` = `g`.`id` GROUP BY `album_id` HAVING $conv(" . $this->sqlGroupConcat('`g`.`name`') . ") $sqlOp $conv(?)) mysqlhack)"; |
||
| 480 | case 'artist_genre': return "`artist_id` IN (SELECT * FROM (SELECT `artist_id` FROM `*PREFIX*music_tracks` `t` JOIN `*PREFIX*music_genres` `g` ON `t`.`genre_id` = `g`.`id` GROUP BY `artist_id` HAVING $conv(" . $this->sqlGroupConcat('`g`.`name`') . ") $sqlOp $conv(?)) mysqlhack)"; |
||
| 481 | case 'no_genre': return ($sqlOp == 'IS NOT NULL') ? '`genre`.`name` = ""' : '`genre`.`name` != ""'; |
||
| 482 | case 'playlist': return "$sqlOp EXISTS (SELECT 1 from `*PREFIX*music_playlists` `p` WHERE `p`.`id` = ? AND `p`.`track_ids` LIKE " . $this->sqlConcat("'%|'", "`*PREFIX*music_tracks`.`id`", "'|%'") . ')'; |
||
| 483 | case 'playlist_name': return "EXISTS (SELECT 1 from `*PREFIX*music_playlists` `p` WHERE $conv(`p`.`name`) $sqlOp $conv(?) AND `p`.`track_ids` LIKE " . $this->sqlConcat("'%|'", "`*PREFIX*music_tracks`.`id`", "'|%'") . ')'; |
||
| 484 | case 'recent_played': return "`*PREFIX*music_tracks`.`id` IN (SELECT * FROM (SELECT `id` FROM `*PREFIX*music_tracks` WHERE `user_id` = ? ORDER BY `last_played` DESC LIMIT $sqlOp) mysqlhack)"; |
||
| 485 | case 'file': return "$conv(`file`.`name`) $sqlOp $conv(?)"; |
||
| 486 | case 'mbid_song': return parent::advFormatSqlCondition('mbid', $sqlOp, $conv); // alias |
||
| 487 | case 'mbid_album': return "`album_id` IN (SELECT `id` from `*PREFIX*music_albums` `al` WHERE `al`.`mbid` $sqlOp ?)"; |
||
| 488 | case 'mbid_artist': return "`artist`.`mbid` $sqlOp ?"; |
||
| 489 | default: return parent::advFormatSqlCondition($rule, $sqlOp, $conv); |
||
| 490 | } |
||
| 491 | } |
||
| 492 | |||
| 493 | private static function formatAdvSearchAnywhereCond(string $sqlOp, string $conv) : string { |
||
| 509 | } |
||
| 510 | |||
| 511 | /** |
||
| 512 | * {@inheritdoc} |
||
| 513 | * @see \OCA\Music\Db\BaseMapper::findUniqueEntity() |
||
| 514 | * @param Track $track |
||
| 515 | * @return Track |
||
| 516 | */ |
||
| 517 | protected function findUniqueEntity(Entity $track) : Entity { |
||
| 518 | return $this->findByFileId($track->getFileId(), $track->getUserId()); |
||
| 519 | } |
||
| 520 | } |
||
| 521 |