2018-08-29 06:15:11 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Repositories;
|
|
|
|
|
2024-01-11 22:14:22 +00:00
|
|
|
use App\Builders\SongBuilder;
|
2024-01-18 11:13:05 +00:00
|
|
|
use App\Facades\License;
|
2022-06-10 10:47:46 +00:00
|
|
|
use App\Models\Album;
|
|
|
|
use App\Models\Artist;
|
|
|
|
use App\Models\Playlist;
|
2018-08-29 06:15:11 +00:00
|
|
|
use App\Models\Song;
|
2022-06-10 10:47:46 +00:00
|
|
|
use App\Models\User;
|
2022-10-21 20:06:43 +00:00
|
|
|
use App\Values\Genre;
|
2022-06-10 10:47:46 +00:00
|
|
|
use Illuminate\Contracts\Pagination\Paginator;
|
2022-07-27 15:32:36 +00:00
|
|
|
use Illuminate\Support\Collection;
|
2018-08-29 06:15:11 +00:00
|
|
|
|
2022-07-29 06:47:10 +00:00
|
|
|
class SongRepository extends Repository
|
2018-08-29 06:15:11 +00:00
|
|
|
{
|
2022-06-10 10:47:46 +00:00
|
|
|
private const DEFAULT_QUEUE_LIMIT = 500;
|
|
|
|
|
2024-02-04 20:31:01 +00:00
|
|
|
public function findOneByPath(string $path): ?Song
|
2018-08-29 06:15:11 +00:00
|
|
|
{
|
2022-08-09 18:45:11 +00:00
|
|
|
return Song::query()->where('path', $path)->first();
|
2021-12-06 16:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @return Collection|array<Song> */
|
2024-02-04 20:31:01 +00:00
|
|
|
public function getAllStoredOnCloud(): Collection
|
2021-12-06 16:12:47 +00:00
|
|
|
{
|
2024-02-04 20:31:01 +00:00
|
|
|
return Song::query()->storedOnCloud()->get();
|
2018-08-29 06:15:11 +00:00
|
|
|
}
|
2022-06-10 10:47:46 +00:00
|
|
|
|
|
|
|
/** @return Collection|array<array-key, Song> */
|
|
|
|
public function getRecentlyAdded(int $count = 10, ?User $scopedUser = null): Collection
|
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
|
|
|
return Song::query()
|
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
|
|
|
->latest()
|
|
|
|
->limit($count)
|
|
|
|
->get();
|
2022-06-10 10:47:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @return Collection|array<array-key, Song> */
|
|
|
|
public function getMostPlayed(int $count = 7, ?User $scopedUser = null): Collection
|
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
2022-08-09 18:45:11 +00:00
|
|
|
return Song::query()
|
2024-01-03 17:02:18 +00:00
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser, requiresInteractions: true)
|
2022-06-10 10:47:46 +00:00
|
|
|
->where('interactions.play_count', '>', 0)
|
|
|
|
->orderByDesc('interactions.play_count')
|
|
|
|
->limit($count)
|
|
|
|
->get();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @return Collection|array<array-key, Song> */
|
|
|
|
public function getRecentlyPlayed(int $count = 7, ?User $scopedUser = null): Collection
|
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
2022-08-09 18:45:11 +00:00
|
|
|
return Song::query()
|
2024-01-03 17:02:18 +00:00
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser, requiresInteractions: true)
|
2022-11-08 17:38:28 +00:00
|
|
|
->orderByDesc('interactions.last_played_at')
|
2022-06-10 10:47:46 +00:00
|
|
|
->limit($count)
|
|
|
|
->get();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getForListing(
|
|
|
|
string $sortColumn,
|
|
|
|
string $sortDirection,
|
2024-01-12 14:41:02 +00:00
|
|
|
bool $ownSongsOnly = false,
|
2022-06-10 10:47:46 +00:00
|
|
|
?User $scopedUser = null,
|
|
|
|
int $perPage = 50
|
|
|
|
): Paginator {
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
|
|
|
return Song::query()
|
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
2024-01-12 14:41:02 +00:00
|
|
|
->when($ownSongsOnly, static fn (SongBuilder $query) => $query->where('songs.owner_id', $scopedUser->id))
|
2024-01-03 17:02:18 +00:00
|
|
|
->sort($sortColumn, $sortDirection)
|
2022-06-10 10:47:46 +00:00
|
|
|
->simplePaginate($perPage);
|
|
|
|
}
|
|
|
|
|
2022-10-21 20:06:43 +00:00
|
|
|
public function getByGenre(
|
|
|
|
string $genre,
|
|
|
|
string $sortColumn,
|
|
|
|
string $sortDirection,
|
|
|
|
?User $scopedUser = null,
|
|
|
|
int $perPage = 50
|
|
|
|
): Paginator {
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
|
|
|
return Song::query()
|
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
|
|
|
->where('genre', $genre)
|
|
|
|
->sort($sortColumn, $sortDirection)
|
2022-10-21 20:06:43 +00:00
|
|
|
->simplePaginate($perPage);
|
|
|
|
}
|
|
|
|
|
2022-06-10 10:47:46 +00:00
|
|
|
/** @return Collection|array<array-key, Song> */
|
|
|
|
public function getForQueue(
|
|
|
|
string $sortColumn,
|
|
|
|
string $sortDirection,
|
2022-07-27 09:30:04 +00:00
|
|
|
int $limit = self::DEFAULT_QUEUE_LIMIT,
|
2022-06-10 10:47:46 +00:00
|
|
|
?User $scopedUser = null,
|
|
|
|
): Collection {
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
|
|
|
return Song::query()
|
2024-01-25 16:21:26 +00:00
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
|
|
|
->sort($sortColumn, $sortDirection)
|
|
|
|
->limit($limit)
|
|
|
|
->get();
|
2022-06-10 10:47:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @return Collection|array<array-key, Song> */
|
|
|
|
public function getFavorites(?User $scopedUser = null): Collection
|
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
|
|
|
return Song::query()
|
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
|
|
|
->where('interactions.liked', true)
|
|
|
|
->get();
|
2022-06-10 10:47:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @return Collection|array<array-key, Song> */
|
|
|
|
public function getByAlbum(Album $album, ?User $scopedUser = null): Collection
|
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
2022-08-09 18:45:11 +00:00
|
|
|
return Song::query()
|
2024-01-03 17:02:18 +00:00
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
2022-06-10 10:47:46 +00:00
|
|
|
->where('album_id', $album->id)
|
|
|
|
->orderBy('songs.disc')
|
2023-06-05 21:27:47 +00:00
|
|
|
->orderBy('songs.track')
|
2022-06-10 10:47:46 +00:00
|
|
|
->orderBy('songs.title')
|
|
|
|
->get();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @return Collection|array<array-key, Song> */
|
|
|
|
public function getByArtist(Artist $artist, ?User $scopedUser = null): Collection
|
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
2022-08-09 18:45:11 +00:00
|
|
|
return Song::query()
|
2024-01-03 17:02:18 +00:00
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
2022-06-10 10:47:46 +00:00
|
|
|
->where('songs.artist_id', $artist->id)
|
2022-10-10 08:29:24 +00:00
|
|
|
->orWhere('albums.artist_id', $artist->id)
|
2022-06-10 10:47:46 +00:00
|
|
|
->orderBy('albums.name')
|
|
|
|
->orderBy('songs.disc')
|
2023-06-05 21:27:47 +00:00
|
|
|
->orderBy('songs.track')
|
2022-06-10 10:47:46 +00:00
|
|
|
->orderBy('songs.title')
|
|
|
|
->get();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @return Collection|array<array-key, Song> */
|
|
|
|
public function getByStandardPlaylist(Playlist $playlist, ?User $scopedUser = null): Collection
|
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
2022-08-09 18:45:11 +00:00
|
|
|
return Song::query()
|
2024-01-03 17:02:18 +00:00
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
2022-06-10 10:47:46 +00:00
|
|
|
->leftJoin('playlist_song', 'songs.id', '=', 'playlist_song.song_id')
|
|
|
|
->leftJoin('playlists', 'playlists.id', '=', 'playlist_song.playlist_id')
|
2024-01-18 11:13:05 +00:00
|
|
|
->when(License::isPlus(), static function (SongBuilder $query): SongBuilder {
|
|
|
|
return
|
|
|
|
$query->join('users as collaborators', 'playlist_song.user_id', '=', 'collaborators.id')
|
2024-01-25 16:21:26 +00:00
|
|
|
->addSelect(
|
|
|
|
'collaborators.id as collaborator_id',
|
|
|
|
'collaborators.name as collaborator_name',
|
|
|
|
'collaborators.email as collaborator_email',
|
2024-04-04 22:20:42 +00:00
|
|
|
'collaborators.avatar as collaborator_avatar',
|
2024-01-25 16:21:26 +00:00
|
|
|
'playlist_song.created_at as added_at'
|
|
|
|
);
|
2024-01-18 11:13:05 +00:00
|
|
|
})
|
2022-06-10 10:47:46 +00:00
|
|
|
->where('playlists.id', $playlist->id)
|
2024-01-29 21:58:50 +00:00
|
|
|
->orderBy('playlist_song.position')
|
2022-06-10 10:47:46 +00:00
|
|
|
->get();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @return Collection|array<array-key, Song> */
|
|
|
|
public function getRandom(int $limit, ?User $scopedUser = null): Collection
|
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
|
|
|
return Song::query()
|
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
|
|
|
->inRandomOrder()
|
|
|
|
->limit($limit)
|
|
|
|
->get();
|
2022-06-10 10:47:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @return Collection|array<array-key, Song> */
|
2024-01-01 20:38:41 +00:00
|
|
|
public function getMany(array $ids, bool $inThatOrder = false, ?User $scopedUser = null): Collection
|
2022-06-10 10:47:46 +00:00
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
2024-01-01 11:40:21 +00:00
|
|
|
$songs = Song::query()
|
2024-01-03 17:02:18 +00:00
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
2024-01-01 11:40:21 +00:00
|
|
|
->whereIn('songs.id', $ids)
|
|
|
|
->get();
|
|
|
|
|
|
|
|
return $inThatOrder ? $songs->orderByArray($ids) : $songs;
|
2022-06-10 10:47:46 +00:00
|
|
|
}
|
|
|
|
|
2024-01-25 16:21:26 +00:00
|
|
|
/**
|
|
|
|
* Gets several songs, but also includes collaborative information.
|
|
|
|
*
|
|
|
|
* @return Collection|array<array-key, Song>
|
|
|
|
*/
|
|
|
|
public function getManyInCollaborativeContext(array $ids, ?User $scopedUser = null): Collection
|
|
|
|
{
|
|
|
|
/** @var ?User $scopedUser */
|
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
|
|
|
return Song::query()
|
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
|
|
|
->when(License::isPlus(), static function (SongBuilder $query): SongBuilder {
|
|
|
|
return
|
|
|
|
$query->leftJoin('playlist_song', 'songs.id', '=', 'playlist_song.song_id')
|
|
|
|
->leftJoin('playlists', 'playlists.id', '=', 'playlist_song.playlist_id')
|
|
|
|
->join('users as collaborators', 'playlist_song.user_id', '=', 'collaborators.id')
|
|
|
|
->addSelect(
|
|
|
|
'collaborators.id as collaborator_id',
|
|
|
|
'collaborators.name as collaborator_name',
|
|
|
|
'collaborators.email as collaborator_email',
|
|
|
|
'playlist_song.created_at as added_at'
|
|
|
|
);
|
|
|
|
})
|
|
|
|
->whereIn('songs.id', $ids)
|
|
|
|
->get();
|
|
|
|
}
|
|
|
|
|
2024-01-10 23:11:45 +00:00
|
|
|
/** @param string $id */
|
2024-01-01 20:38:41 +00:00
|
|
|
public function getOne($id, ?User $scopedUser = null): Song
|
2022-06-10 10:47:46 +00:00
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
2022-06-10 10:47:46 +00:00
|
|
|
|
2024-01-03 17:02:18 +00:00
|
|
|
return Song::query()
|
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
|
|
|
->findOrFail($id);
|
2024-01-01 11:40:21 +00:00
|
|
|
}
|
|
|
|
|
2024-01-12 14:41:02 +00:00
|
|
|
/** @param string $id */
|
2024-01-03 17:02:18 +00:00
|
|
|
public function findOne($id, ?User $scopedUser = null): ?Song
|
2022-06-10 10:47:46 +00:00
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
2022-06-10 10:47:46 +00:00
|
|
|
|
2024-01-03 17:02:18 +00:00
|
|
|
return Song::query()
|
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser ?? $this->auth->user())
|
|
|
|
->find($id);
|
2022-06-10 10:47:46 +00:00
|
|
|
}
|
|
|
|
|
2024-01-03 17:02:18 +00:00
|
|
|
public function count(?User $scopedUser = null): int
|
2022-06-10 10:47:46 +00:00
|
|
|
{
|
2024-01-03 17:02:18 +00:00
|
|
|
return Song::query()->accessibleBy($scopedUser ?? auth()->user())->count();
|
2022-06-10 10:47:46 +00:00
|
|
|
}
|
|
|
|
|
2024-01-03 17:02:18 +00:00
|
|
|
public function getTotalLength(?User $scopedUser = null): float
|
2022-06-10 10:47:46 +00:00
|
|
|
{
|
2024-01-03 17:02:18 +00:00
|
|
|
return Song::query()->accessibleBy($scopedUser ?? auth()->user())->sum('length');
|
2022-06-10 10:47:46 +00:00
|
|
|
}
|
2022-10-21 20:06:43 +00:00
|
|
|
|
|
|
|
/** @return Collection|array<array-key, Song> */
|
|
|
|
public function getRandomByGenre(string $genre, int $limit, ?User $scopedUser = null): Collection
|
|
|
|
{
|
2024-01-07 12:43:10 +00:00
|
|
|
/** @var ?User $scopedUser */
|
2024-01-03 17:02:18 +00:00
|
|
|
$scopedUser ??= $this->auth->user();
|
|
|
|
|
2022-10-21 20:06:43 +00:00
|
|
|
return Song::query()
|
2024-01-03 17:02:18 +00:00
|
|
|
->accessibleBy($scopedUser)
|
|
|
|
->withMetaFor($scopedUser)
|
2022-10-21 20:06:43 +00:00
|
|
|
->where('genre', $genre === Genre::NO_GENRE ? '' : $genre)
|
|
|
|
->limit($limit)
|
|
|
|
->inRandomOrder()
|
|
|
|
->get();
|
|
|
|
}
|
2018-08-29 06:15:11 +00:00
|
|
|
}
|