koel/app/Repositories/SongRepository.php

318 lines
10 KiB
PHP
Raw Normal View History

2018-08-29 06:15:11 +00:00
<?php
namespace App\Repositories;
use App\Builders\SongBuilder;
2024-05-19 05:49:42 +00:00
use App\Enums\MediaType;
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;
2024-05-19 05:49:42 +00:00
use App\Models\Podcast\Podcast;
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
2024-04-24 21:58:19 +00:00
/** @extends Repository<Song> */
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;
public function findOneByPath(string $path): ?Song
2018-08-29 06:15:11 +00:00
{
return Song::query()->where('path', $path)->first();
}
2024-04-24 21:58:19 +00:00
/** @return Collection|array<array-key, Song> */
public function getAllStoredOnCloud(): Collection
{
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-03 17:02:18 +00:00
$scopedUser ??= $this->auth->user();
return Song::query()
2024-05-19 05:49:42 +00:00
->typeOf(MediaType::SONG)
2024-01-03 17:02:18 +00:00
->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-03 17:02:18 +00:00
$scopedUser ??= $this->auth->user();
return Song::query()
2024-05-19 05:49:42 +00:00
->typeOf(MediaType::SONG)
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-03 17:02:18 +00:00
$scopedUser ??= $this->auth->user();
return Song::query()
2024-01-03 17:02:18 +00:00
->accessibleBy($scopedUser)
->withMetaFor($scopedUser, requiresInteractions: true)
->orderByDesc('interactions.last_played_at')
2022-06-10 10:47:46 +00:00
->limit($count)
->get();
}
public function getForListing(
2024-05-19 05:49:42 +00:00
array $sortColumns,
2022-06-10 10:47:46 +00:00
string $sortDirection,
bool $ownSongsOnly = false,
2022-06-10 10:47:46 +00:00
?User $scopedUser = null,
int $perPage = 50
): Paginator {
2024-01-03 17:02:18 +00:00
$scopedUser ??= $this->auth->user();
return Song::query()
2024-05-19 05:49:42 +00:00
->typeOf(MediaType::SONG)
2024-01-03 17:02:18 +00:00
->accessibleBy($scopedUser)
->withMetaFor($scopedUser)
->when($ownSongsOnly, static fn (SongBuilder $query) => $query->where('songs.owner_id', $scopedUser->id))
2024-05-19 05:49:42 +00:00
->sort($sortColumns, $sortDirection)
2022-06-10 10:47:46 +00:00
->simplePaginate($perPage);
}
2022-10-21 20:06:43 +00:00
public function getByGenre(
string $genre,
2024-05-19 05:49:42 +00:00
array $sortColumns,
2022-10-21 20:06:43 +00:00
string $sortDirection,
?User $scopedUser = null,
int $perPage = 50
): Paginator {
2024-01-03 17:02:18 +00:00
$scopedUser ??= $this->auth->user();
return Song::query()
->accessibleBy($scopedUser)
->withMetaFor($scopedUser)
->where('genre', $genre)
2024-05-19 05:49:42 +00:00
->sort($sortColumns, $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(
2024-05-19 05:49:42 +00:00
array $sortColumns,
2022-06-10 10:47:46 +00:00
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-03 17:02:18 +00:00
$scopedUser ??= $this->auth->user();
return Song::query()
->accessibleBy($scopedUser)
->withMetaFor($scopedUser)
2024-05-19 05:49:42 +00:00
->sort($sortColumns, $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-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-03 17:02:18 +00:00
$scopedUser ??= $this->auth->user();
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')
->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-03 17:02:18 +00:00
$scopedUser ??= $this->auth->user();
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)
->orWhere('albums.artist_id', $artist->id)
2022-06-10 10:47:46 +00:00
->orderBy('albums.name')
->orderBy('songs.disc')
->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-03 17:02:18 +00:00
$scopedUser ??= $this->auth->user();
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')
->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',
'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)
->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-03 17:02:18 +00:00
$scopedUser ??= $this->auth->user();
return Song::query()
2024-05-19 05:49:42 +00:00
->typeOf(MediaType::SONG)
2024-01-03 17:02:18 +00:00
->accessibleBy($scopedUser)
->withMetaFor($scopedUser)
->inRandomOrder()
->limit($limit)
->get();
2022-06-10 10:47:46 +00:00
}
/** @return Collection|array<array-key, Song> */
public function getMany(array $ids, bool $inThatOrder = false, ?User $scopedUser = null): Collection
2022-06-10 10:47:46 +00:00
{
2024-01-03 17:02:18 +00:00
$scopedUser ??= $this->auth->user();
$songs = Song::query()
2024-01-03 17:02:18 +00:00
->accessibleBy($scopedUser)
->withMetaFor($scopedUser)
->whereIn('songs.id', $ids)
->get();
return $inThatOrder ? $songs->orderByArray($ids) : $songs;
2022-06-10 10:47:46 +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
{
$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 */
public function getOne($id, ?User $scopedUser = null): Song
2022-06-10 10:47:46 +00:00
{
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);
}
/** @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-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-05-19 05:49:42 +00:00
public function countSongs(?User $scopedUser = null): int
2022-06-10 10:47:46 +00:00
{
2024-05-19 05:49:42 +00:00
return Song::query()
->typeOf(MediaType::SONG)
->accessibleBy($scopedUser ?? auth()->user())
->count();
2022-06-10 10:47:46 +00:00
}
2024-05-19 05:49:42 +00:00
public function getTotalSongLength(?User $scopedUser = null): float
2022-06-10 10:47:46 +00:00
{
2024-05-19 05:49:42 +00:00
return Song::query()
->typeOf(MediaType::SONG)
->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-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();
}
2024-05-19 05:49:42 +00:00
/** @return array<string> */
public function getEpisodeGuidsByPodcast(Podcast $podcast): array
{
return $podcast->episodes()->pluck('episode_guid')->toArray();
}
/** @return Collection<Song> */
public function getEpisodesByPodcast(Podcast $podcast): Collection
{
return $podcast->episodes;
}
2018-08-29 06:15:11 +00:00
}