diff --git a/app/Builders/AlbumBuilder.php b/app/Builders/AlbumBuilder.php index c6a2acb1..2f9e90d6 100644 --- a/app/Builders/AlbumBuilder.php +++ b/app/Builders/AlbumBuilder.php @@ -3,10 +3,7 @@ namespace App\Builders; use App\Models\Album; -use App\Models\User; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Database\Query\JoinClause; -use Illuminate\Support\Facades\DB; class AlbumBuilder extends Builder { @@ -14,19 +11,4 @@ class AlbumBuilder extends Builder { return $this->whereNot('albums.id', Album::UNKNOWN_ID); } - - public function withMeta(User $user): static - { - $integer = $this->integerCastType(); - - return $this->with('artist') - ->leftJoin('songs', 'albums.id', '=', 'songs.album_id') - ->leftJoin('interactions', static function (JoinClause $join) use ($user): void { - $join->on('songs.id', '=', 'interactions.song_id')->where('interactions.user_id', $user->id); - }) - ->groupBy('albums.id') - ->select('albums.*', DB::raw("CAST(SUM(interactions.play_count) AS $integer) AS play_count")) - ->withCount('songs AS song_count') - ->withSum('songs AS length', 'length'); - } } diff --git a/app/Builders/ArtistBuilder.php b/app/Builders/ArtistBuilder.php index 29dd6fd5..9bc7ff6e 100644 --- a/app/Builders/ArtistBuilder.php +++ b/app/Builders/ArtistBuilder.php @@ -3,10 +3,7 @@ namespace App\Builders; use App\Models\Artist; -use App\Models\User; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Database\Query\JoinClause; -use Illuminate\Support\Facades\DB; class ArtistBuilder extends Builder { @@ -14,22 +11,4 @@ class ArtistBuilder extends Builder { return $this->whereNotIn('artists.id', [Artist::UNKNOWN_ID, Artist::VARIOUS_ID]); } - - public function withMeta(User $user): static - { - $integer = $this->integerCastType(); - - return $this->leftJoin('songs', 'artists.id', '=', 'songs.artist_id') - ->leftJoin('interactions', static function (JoinClause $join) use ($user): void { - $join->on('interactions.song_id', '=', 'songs.id')->where('interactions.user_id', $user->id); - }) - ->groupBy('artists.id') - ->select([ - 'artists.*', - DB::raw("CAST(SUM(interactions.play_count) AS $integer) AS play_count"), - DB::raw('COUNT(DISTINCT songs.album_id) AS album_count'), - ]) - ->withCount('songs AS song_count') - ->withSum('songs AS length', 'length'); - } } diff --git a/app/Facades/Download.php b/app/Facades/Download.php index 924e1ae3..7104fca7 100644 --- a/app/Facades/Download.php +++ b/app/Facades/Download.php @@ -6,7 +6,7 @@ use App\Models\Song; use Illuminate\Support\Facades\Facade; /** - * @method static fromSong(Song $song) + * @method static string fromSong(Song $song) */ class Download extends Facade { diff --git a/app/Http/Controllers/API/SongController.php b/app/Http/Controllers/API/SongController.php index c8a5e8c5..d69a4e9a 100644 --- a/app/Http/Controllers/API/SongController.php +++ b/app/Http/Controllers/API/SongController.php @@ -7,30 +7,26 @@ use App\Http\Requests\API\SongUpdateRequest; use App\Http\Resources\AlbumResource; use App\Http\Resources\ArtistResource; use App\Http\Resources\SongResource; -use App\Models\User; use App\Repositories\AlbumRepository; use App\Repositories\ArtistRepository; use App\Services\LibraryManager; use App\Services\SongService; use App\Values\SongUpdateData; -use Illuminate\Contracts\Auth\Authenticatable; class SongController extends Controller { - /** @param User $user */ public function __construct( private SongService $songService, private AlbumRepository $albumRepository, private ArtistRepository $artistRepository, - private LibraryManager $libraryManager, - private ?Authenticatable $user + private LibraryManager $libraryManager ) { } public function update(SongUpdateRequest $request) { $updatedSongs = $this->songService->updateSongs($request->songs, SongUpdateData::fromRequest($request)); - $albums = $this->albumRepository->getByIds($updatedSongs->pluck('album_id')->toArray(), $this->user); + $albums = $this->albumRepository->getByIds($updatedSongs->pluck('album_id')->toArray()); $artists = $this->artistRepository->getByIds( array_merge( diff --git a/app/Http/Controllers/V6/API/AlbumController.php b/app/Http/Controllers/V6/API/AlbumController.php index b6f95c01..1f2ffff3 100644 --- a/app/Http/Controllers/V6/API/AlbumController.php +++ b/app/Http/Controllers/V6/API/AlbumController.php @@ -5,24 +5,21 @@ namespace App\Http\Controllers\V6\API; use App\Http\Controllers\Controller; use App\Http\Resources\AlbumResource; use App\Models\Album; -use App\Models\User; use App\Repositories\AlbumRepository; -use Illuminate\Contracts\Auth\Authenticatable; class AlbumController extends Controller { - /** @param User $user */ - public function __construct(private AlbumRepository $repository, private ?Authenticatable $user) + public function __construct(private AlbumRepository $repository) { } public function index() { - return AlbumResource::collection($this->repository->paginate($this->user)); + return AlbumResource::collection($this->repository->paginate()); } public function show(Album $album) { - return AlbumResource::make($this->repository->getOne($album->id, $this->user)); + return AlbumResource::make($this->repository->getOne($album->id)); } } diff --git a/app/Http/Controllers/V6/API/ArtistController.php b/app/Http/Controllers/V6/API/ArtistController.php index d51a8505..e10fece8 100644 --- a/app/Http/Controllers/V6/API/ArtistController.php +++ b/app/Http/Controllers/V6/API/ArtistController.php @@ -5,24 +5,21 @@ namespace App\Http\Controllers\V6\API; use App\Http\Controllers\Controller; use App\Http\Resources\ArtistResource; use App\Models\Artist; -use App\Models\User; use App\Repositories\ArtistRepository; -use Illuminate\Contracts\Auth\Authenticatable; class ArtistController extends Controller { - /** @param User $user */ - public function __construct(private ArtistRepository $repository, private ?Authenticatable $user) + public function __construct(private ArtistRepository $repository) { } public function index() { - return ArtistResource::collection($this->repository->paginate($this->user)); + return ArtistResource::collection($this->repository->paginate()); } public function show(Artist $artist) { - return ArtistResource::make($this->repository->getOne($artist->id, $this->user)); + return ArtistResource::make($this->repository->getOne($artist->id)); } } diff --git a/app/Http/Controllers/V6/API/QueueController.php b/app/Http/Controllers/V6/API/QueueController.php index 7828ac9c..91f4445f 100644 --- a/app/Http/Controllers/V6/API/QueueController.php +++ b/app/Http/Controllers/V6/API/QueueController.php @@ -26,7 +26,7 @@ class QueueController extends Controller $request->sort, $request->order, $request->limit, - $this->user, + $this->user ) ); } diff --git a/app/Http/Resources/AlbumResource.php b/app/Http/Resources/AlbumResource.php index 0e3860a2..2f748f8a 100644 --- a/app/Http/Resources/AlbumResource.php +++ b/app/Http/Resources/AlbumResource.php @@ -23,9 +23,6 @@ class AlbumResource extends JsonResource 'artist_name' => $this->album->artist->name, 'cover' => $this->album->cover, 'created_at' => $this->album->created_at, - 'length' => (float) $this->album->length, - 'play_count' => (int) $this->album->play_count, - 'song_count' => (int) $this->album->song_count, ]; } } diff --git a/app/Http/Resources/ArtistResource.php b/app/Http/Resources/ArtistResource.php index 310d7f15..63f7ebbd 100644 --- a/app/Http/Resources/ArtistResource.php +++ b/app/Http/Resources/ArtistResource.php @@ -20,10 +20,6 @@ class ArtistResource extends JsonResource 'id' => $this->artist->id, 'name' => $this->artist->name, 'image' => $this->artist->image, - 'length' => (float) $this->artist->length, - 'play_count' => (int) $this->artist->play_count, - 'song_count' => (int) $this->artist->song_count, - 'album_count' => (int) $this->artist->album_count, 'created_at' => $this->artist->created_at, ]; } diff --git a/app/Repositories/AlbumRepository.php b/app/Repositories/AlbumRepository.php index ef6b212d..b420e875 100644 --- a/app/Repositories/AlbumRepository.php +++ b/app/Repositories/AlbumRepository.php @@ -6,57 +6,57 @@ use App\Models\Album; use App\Models\User; use App\Repositories\Traits\Searchable; use Illuminate\Contracts\Pagination\Paginator; +use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; class AlbumRepository extends Repository { use Searchable; - public function getOne(int $id, ?User $scopedUser = null): Album + public function getOne(int $id): Album { - return Album::query() - ->withMeta($scopedUser ?? $this->auth->user()) - ->where('albums.id', $id) - ->first(); + return Album::query()->find($id); } /** @return Collection|array */ - public function getRecentlyAdded(int $count = 6, ?User $scopedUser = null): Collection + public function getRecentlyAdded(int $count = 6): Collection { return Album::query() - ->withMeta($scopedUser ?? $this->auth->user()) ->isStandard() - ->latest('albums.created_at') + ->latest('created_at') ->limit($count) ->get(); } /** @return Collection|array */ - public function getMostPlayed(int $count = 6, ?User $scopedUser = null): Collection + public function getMostPlayed(int $count = 6, ?User $user = null): Collection { + $user ??= $this->auth->user(); + return Album::query() - ->withMeta($scopedUser ?? $this->auth->user()) + ->leftJoin('songs', 'albums.id', 'songs.album_id') + ->leftJoin('interactions', static function (JoinClause $join) use ($user): void { + $join->on('songs.id', 'interactions.song_id')->where('interactions.user_id', $user->id); + }) ->isStandard() ->orderByDesc('play_count') ->limit($count) - ->get(); + ->get('albums.*'); } /** @return Collection|array */ - public function getByIds(array $ids, ?User $scopedUser = null): Collection + public function getByIds(array $ids): Collection { return Album::query() - ->withMeta($scopedUser ?? $this->auth->user()) - ->whereIn('albums.id', $ids) + ->whereIn('id', $ids) ->get(); } - public function paginate(?User $scopedUser = null): Paginator + public function paginate(): Paginator { return Album::query() - ->withMeta($scopedUser ?? $this->auth->user()) ->isStandard() - ->orderBy('albums.name') + ->orderBy('name') ->simplePaginate(21); } } diff --git a/app/Repositories/ArtistRepository.php b/app/Repositories/ArtistRepository.php index fd73b969..0d2d3ff6 100644 --- a/app/Repositories/ArtistRepository.php +++ b/app/Repositories/ArtistRepository.php @@ -7,46 +7,48 @@ use App\Models\User; use App\Repositories\Traits\Searchable; use Illuminate\Contracts\Pagination\Paginator; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Query\JoinClause; class ArtistRepository extends Repository { use Searchable; /** @return Collection|array */ - public function getMostPlayed(int $count = 6, ?User $scopedUser = null): Collection + public function getMostPlayed(int $count = 6, ?User $user = null): Collection { + $user ??= auth()->user(); + return Artist::query() - ->withMeta($scopedUser ?? $this->auth->user()) + ->leftJoin('songs', 'artists.id', '=', 'songs.artist_id') + ->leftJoin('interactions', static function (JoinClause $join) use ($user): void { + $join->on('interactions.song_id', '=', 'songs.id')->where('interactions.user_id', $user->id); + }) + ->groupBy('artists.id') ->isStandard() ->orderByDesc('play_count') ->limit($count) - ->get(); + ->get('artists.*'); } - public function getOne(int $id, ?User $scopedUser = null): Artist + public function getOne(int $id): Artist { - return Artist::query() - ->withMeta($scopedUser ?? $this->auth->user()) - ->where('artists.id', $id) - ->first(); + return Artist::query()->find($id); } /** @return Collection|array */ - public function getByIds(array $ids, ?User $scopedUser = null): Collection + public function getByIds(array $ids): Collection { return Artist::query() - ->withMeta($scopedUser ?? $this->auth->user()) ->isStandard() - ->whereIn('artists.id', $ids) + ->whereIn('id', $ids) ->get(); } - public function paginate(?User $scopedUser = null): Paginator + public function paginate(): Paginator { return Artist::query() - ->withMeta($scopedUser ?? $this->auth->user()) ->isStandard() - ->orderBy('artists.name') + ->orderBy('name') ->simplePaginate(21); } } diff --git a/app/Services/SmartPlaylistService.php b/app/Services/SmartPlaylistService.php index c13418b7..40fcb306 100644 --- a/app/Services/SmartPlaylistService.php +++ b/app/Services/SmartPlaylistService.php @@ -8,13 +8,12 @@ use App\Models\Song; use App\Models\User; use App\Values\SmartPlaylistRule; use App\Values\SmartPlaylistRuleGroup; -use Illuminate\Contracts\Auth\Guard; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; class SmartPlaylistService { - public function __construct(private Guard $auth) + public function __construct() { } @@ -23,7 +22,7 @@ class SmartPlaylistService { throw_unless($playlist->is_smart, NonSmartPlaylistException::create($playlist)); - $query = Song::query()->withMeta($user ?? $this->auth->user()); + $query = Song::query()->withMeta($user ?? $playlist->user); $playlist->rule_groups->each(static function (SmartPlaylistRuleGroup $group, int $index) use ($query): void { $clause = $index === 0 ? 'where' : 'orWhere'; diff --git a/app/Services/V6/SearchService.php b/app/Services/V6/SearchService.php index 5acb259e..035672cc 100644 --- a/app/Services/V6/SearchService.php +++ b/app/Services/V6/SearchService.php @@ -37,14 +37,8 @@ class SearchService Song::search($keywords)->get()->take($count)->pluck('id')->all(), $scopedUser ), - $this->artistRepository->getByIds( - Artist::search($keywords)->get()->take($count)->pluck('id')->all(), - $scopedUser - ), - $this->albumRepository->getByIds( - Album::search($keywords)->get()->take($count)->pluck('id')->all(), - $scopedUser - ), + $this->artistRepository->getByIds(Artist::search($keywords)->get()->take($count)->pluck('id')->all()), + $this->albumRepository->getByIds(Album::search($keywords)->get()->take($count)->pluck('id')->all()), ); } diff --git a/resources/assets/js/__tests__/factory/albumFactory.ts b/resources/assets/js/__tests__/factory/albumFactory.ts index 2489b570..bef939ac 100644 --- a/resources/assets/js/__tests__/factory/albumFactory.ts +++ b/resources/assets/js/__tests__/factory/albumFactory.ts @@ -1,18 +1,13 @@ import { Faker } from '@faker-js/faker' export default (faker: Faker): Album => { - const length = faker.datatype.number({ min: 300 }) - return { type: 'albums', artist_id: faker.datatype.number({ min: 3 }), // avoid Unknown and Various Artist by default artist_name: faker.name.findName(), - song_count: faker.datatype.number(30), id: faker.datatype.number({ min: 2 }), // avoid Unknown Album by default name: faker.lorem.sentence(), cover: faker.image.imageUrl(), - play_count: faker.datatype.number(), - length, created_at: faker.date.past().toISOString() } } diff --git a/resources/assets/js/__tests__/factory/artistFactory.ts b/resources/assets/js/__tests__/factory/artistFactory.ts index b666cab5..228817e8 100644 --- a/resources/assets/js/__tests__/factory/artistFactory.ts +++ b/resources/assets/js/__tests__/factory/artistFactory.ts @@ -1,17 +1,11 @@ import { Faker } from '@faker-js/faker' export default (faker: Faker): Artist => { - const length = faker.datatype.number({ min: 300 }) - return { type: 'artists', id: faker.datatype.number({ min: 3 }), // avoid Unknown and Various Artist by default name: faker.name.findName(), image: 'foo.jpg', - play_count: faker.datatype.number(), - album_count: faker.datatype.number({ max: 10 }), - song_count: faker.datatype.number({ max: 100 }), - length, created_at: faker.date.past().toISOString() } } diff --git a/resources/assets/js/components/album/AlbumCard.spec.ts b/resources/assets/js/components/album/AlbumCard.spec.ts index b5bf51e6..c718ed8a 100644 --- a/resources/assets/js/components/album/AlbumCard.spec.ts +++ b/resources/assets/js/components/album/AlbumCard.spec.ts @@ -11,10 +11,9 @@ let album: Album new class extends UnitTestCase { private renderComponent () { album = factory('album', { + id: 42, name: 'IV', - play_count: 30, - song_count: 10, - length: 123 + artist_name: 'Led Zeppelin' }) return this.render(AlbumCard, { @@ -26,12 +25,8 @@ new class extends UnitTestCase { protected test () { it('renders', () => { - const { getByText, getByTestId } = this.renderComponent() - - expect(getByTestId('name').textContent).toBe('IV') - getByText(/^10 songs.+02:03.+30 plays$/) - getByTestId('shuffle-album') - getByTestId('download-album') + const { html } = this.renderComponent() + expect(html()).toMatchSnapshot() }) it('downloads', async () => { diff --git a/resources/assets/js/components/album/AlbumCard.vue b/resources/assets/js/components/album/AlbumCard.vue index 72a7df19..cd93980e 100644 --- a/resources/assets/js/components/album/AlbumCard.vue +++ b/resources/assets/js/components/album/AlbumCard.vue @@ -18,45 +18,36 @@ {{ album.artist_name }} {{ album.artist_name }}

- - {{ pluralize(album.song_count, 'song') }} - • - {{ duration }} - • - {{ pluralize(album.play_count, 'play') }} - - - - - - - - - + + Shuffle + + • + + Download +