mirror of
https://github.com/koel/koel
synced 2024-11-10 06:34:14 +00:00
chore: some cleanups
This commit is contained in:
parent
3da2900000
commit
e10fc19e12
23 changed files with 112 additions and 159 deletions
|
@ -140,3 +140,11 @@ function collect_sso_providers(): array
|
|||
|
||||
return $providers;
|
||||
}
|
||||
|
||||
function get_mtime(string|SplFileInfo $file): int
|
||||
{
|
||||
$file = is_string($file) ? new SplFileInfo($file) : $file;
|
||||
|
||||
// Workaround for #344, where getMTime() fails for certain files with Unicode names on Windows.
|
||||
return attempt(static fn () => $file->getMTime()) ?? time();
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class SearchVideosRequest extends Request
|
|||
return '/search';
|
||||
}
|
||||
|
||||
/** @return array<mixed> */
|
||||
/** @inheritdoc */
|
||||
protected function defaultQuery(): array
|
||||
{
|
||||
$q = $this->song->title;
|
||||
|
|
|
@ -205,7 +205,7 @@ class Song extends Model
|
|||
return "s3://$bucket/$key";
|
||||
}
|
||||
|
||||
/** @return array<mixed> */
|
||||
/** @inheritdoc */
|
||||
public function toSearchableArray(): array
|
||||
{
|
||||
$array = [
|
||||
|
|
|
@ -68,7 +68,7 @@ abstract class Repository implements RepositoryInterface
|
|||
}
|
||||
|
||||
/** @return T|null */
|
||||
public function getFirstWhere(...$params): ?Model
|
||||
public function findFirstWhere(...$params): ?Model
|
||||
{
|
||||
return $this->model::query()->firstWhere(...$params);
|
||||
}
|
||||
|
|
|
@ -14,11 +14,7 @@ class AllPlayablesAreAccessibleBy implements ValidationRule
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param array<string> $value
|
||||
*/
|
||||
/** @param array<string> $value */
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
$ids = array_unique(Arr::wrap($value));
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
namespace App\Services;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Contracts\Cache\Repository as Cache;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class ApplicationInformationService
|
||||
{
|
||||
public function __construct(private readonly Client $client, private readonly Cache $cache)
|
||||
public function __construct(private readonly Client $client)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ class ApplicationInformationService
|
|||
public function getLatestVersionNumber(): string
|
||||
{
|
||||
return attempt(function () {
|
||||
return $this->cache->remember('latestKoelVersion', now()->addDay(), function (): string {
|
||||
return Cache::remember('latestKoelVersion', now()->addDay(), function (): string {
|
||||
return json_decode($this->client->get('https://api.github.com/repos/koel/koel/tags')->getBody())[0]
|
||||
->name;
|
||||
});
|
||||
|
|
|
@ -8,8 +8,8 @@ use App\Repositories\UserRepository;
|
|||
use App\Values\CompositeToken;
|
||||
use Illuminate\Auth\Events\PasswordReset;
|
||||
use Illuminate\Auth\Passwords\PasswordBroker;
|
||||
use Illuminate\Hashing\HashManager;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
|
||||
class AuthenticationService
|
||||
|
@ -17,21 +17,20 @@ class AuthenticationService
|
|||
public function __construct(
|
||||
private readonly UserRepository $userRepository,
|
||||
private readonly TokenManager $tokenManager,
|
||||
private readonly HashManager $hash,
|
||||
private readonly PasswordBroker $passwordBroker
|
||||
) {
|
||||
}
|
||||
|
||||
public function login(string $email, string $password): CompositeToken
|
||||
{
|
||||
$user = $this->userRepository->getFirstWhere('email', $email);
|
||||
$user = $this->userRepository->findFirstWhere('email', $email);
|
||||
|
||||
if (!$user || !$this->hash->check($password, $user->password)) {
|
||||
if (!$user || !Hash::check($password, $user->password)) {
|
||||
throw new InvalidCredentialsException();
|
||||
}
|
||||
|
||||
if ($this->hash->needsRehash($user->password)) {
|
||||
$user->password = $this->hash->make($password);
|
||||
if (Hash::needsRehash($user->password)) {
|
||||
$user->password = Hash::make($password);
|
||||
$user->save();
|
||||
}
|
||||
|
||||
|
@ -62,8 +61,8 @@ class AuthenticationService
|
|||
'token' => $token,
|
||||
];
|
||||
|
||||
$status = $this->passwordBroker->reset($credentials, function (User $user, string $password): void {
|
||||
$user->password = $this->hash->make($password);
|
||||
$status = $this->passwordBroker->reset($credentials, static function (User $user, string $password): void {
|
||||
$user->password = Hash::make($password);
|
||||
$user->save();
|
||||
event(new PasswordReset($user));
|
||||
});
|
||||
|
|
|
@ -10,8 +10,8 @@ use App\Values\ScanConfiguration;
|
|||
use App\Values\ScanResult;
|
||||
use App\Values\SongScanInformation;
|
||||
use getID3;
|
||||
use Illuminate\Contracts\Cache\Repository as Cache;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use SplFileInfo;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
|
@ -32,7 +32,6 @@ class FileScanner
|
|||
private readonly MediaMetadataService $mediaMetadataService,
|
||||
private readonly SongRepository $songRepository,
|
||||
private readonly SimpleLrcReader $lrcReader,
|
||||
private readonly Cache $cache,
|
||||
private readonly Finder $finder
|
||||
) {
|
||||
}
|
||||
|
@ -43,7 +42,7 @@ class FileScanner
|
|||
|
||||
$this->filePath = $file->getRealPath();
|
||||
$this->song = $this->songRepository->findOneByPath($this->filePath);
|
||||
$this->fileModifiedTime = Helper::getModifiedTime($file);
|
||||
$this->fileModifiedTime = get_mtime($file);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -137,7 +136,7 @@ class FileScanner
|
|||
private function getCoverFileUnderSameDirectory(): ?string
|
||||
{
|
||||
// As directory scanning can be expensive, we cache and reuse the result.
|
||||
return $this->cache->remember(md5($this->filePath . '_cover'), now()->addDay(), function (): ?string {
|
||||
return Cache::remember(md5($this->filePath . '_cover'), now()->addDay(), function (): ?string {
|
||||
$matches = array_keys(
|
||||
iterator_to_array(
|
||||
$this->finder->create()
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use SplFileInfo;
|
||||
|
||||
class Helper
|
||||
{
|
||||
public static function getModifiedTime(string|SplFileInfo $file): int
|
||||
{
|
||||
$file = is_string($file) ? new SplFileInfo($file) : $file;
|
||||
|
||||
// Workaround for #344, where getMTime() fails for certain files with Unicode names on Windows.
|
||||
return attempt(static fn () => $file->getMTime()) ?? time();
|
||||
}
|
||||
}
|
|
@ -5,11 +5,11 @@ namespace App\Services;
|
|||
use App\Http\Integrations\iTunes\ITunesConnector;
|
||||
use App\Http\Integrations\iTunes\Requests\GetTrackRequest;
|
||||
use App\Models\Album;
|
||||
use Illuminate\Cache\Repository as Cache;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class ITunesService
|
||||
{
|
||||
public function __construct(private readonly ITunesConnector $connector, private readonly Cache $cache)
|
||||
public function __construct(private readonly ITunesConnector $connector)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ class ITunesService
|
|||
$request = new GetTrackRequest($trackName, $album);
|
||||
$hash = md5(serialize($request->query()));
|
||||
|
||||
return $this->cache->remember(
|
||||
return Cache::remember(
|
||||
"itunes.track.$hash",
|
||||
now()->addWeek(),
|
||||
function () use ($request): ?string {
|
||||
|
|
|
@ -6,16 +6,16 @@ use App\Events\MultipleSongsLiked;
|
|||
use App\Events\MultipleSongsUnliked;
|
||||
use App\Events\SongLikeToggled;
|
||||
use App\Models\Interaction;
|
||||
use App\Models\Song;
|
||||
use App\Models\Song as Playable;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class InteractionService
|
||||
{
|
||||
public function increasePlayCount(Song $song, User $user): Interaction
|
||||
public function increasePlayCount(Playable $playable, User $user): Interaction
|
||||
{
|
||||
return tap(Interaction::query()->firstOrCreate([
|
||||
'song_id' => $song->id,
|
||||
'song_id' => $playable->id,
|
||||
'user_id' => $user->id,
|
||||
]), static function (Interaction $interaction): void {
|
||||
if (!$interaction->exists) {
|
||||
|
@ -30,14 +30,14 @@ class InteractionService
|
|||
}
|
||||
|
||||
/**
|
||||
* Like or unlike a song as a user.
|
||||
* Like or unlike a song/episode as a user.
|
||||
*
|
||||
* @return Interaction The affected Interaction object
|
||||
*/
|
||||
public function toggleLike(Song $song, User $user): Interaction
|
||||
public function toggleLike(Playable $playable, User $user): Interaction
|
||||
{
|
||||
return tap(Interaction::query()->firstOrCreate([
|
||||
'song_id' => $song->id,
|
||||
'song_id' => $playable->id,
|
||||
'user_id' => $user->id,
|
||||
]), static function (Interaction $interaction): void {
|
||||
$interaction->liked = !$interaction->liked;
|
||||
|
@ -48,17 +48,17 @@ class InteractionService
|
|||
}
|
||||
|
||||
/**
|
||||
* Like several songs at once as a user.
|
||||
* Like several songs/episodes at once as a user.
|
||||
*
|
||||
* @param Collection<array-key, Song> $songs
|
||||
* @param Collection<array-key, Playable> $playables
|
||||
*
|
||||
* @return Collection<array-key, Interaction> The array of Interaction objects
|
||||
*/
|
||||
public function likeMany(Collection $songs, User $user): Collection
|
||||
public function likeMany(Collection $playables, User $user): Collection
|
||||
{
|
||||
$interactions = $songs->map(static function (Song $song) use ($user): Interaction {
|
||||
$interactions = $playables->map(static function (Playable $playable) use ($user): Interaction {
|
||||
return tap(Interaction::query()->firstOrCreate([
|
||||
'song_id' => $song->id,
|
||||
'song_id' => $playable->id,
|
||||
'user_id' => $user->id,
|
||||
]), static function (Interaction $interaction): void {
|
||||
$interaction->play_count ??= 0;
|
||||
|
@ -67,23 +67,23 @@ class InteractionService
|
|||
});
|
||||
});
|
||||
|
||||
event(new MultipleSongsLiked($songs, $user));
|
||||
event(new MultipleSongsLiked($playables, $user));
|
||||
|
||||
return $interactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlike several songs at once.
|
||||
* Unlike several songs/episodes at once.
|
||||
*
|
||||
* @param array<array-key, Song>|Collection $songs
|
||||
* @param array<array-key, Playable>|Collection $playables
|
||||
*/
|
||||
public function unlikeMany(Collection $songs, User $user): void
|
||||
public function unlikeMany(Collection $playables, User $user): void
|
||||
{
|
||||
Interaction::query()
|
||||
->whereIn('song_id', $songs->pluck('id')->all())
|
||||
->whereIn('song_id', $playables->pluck('id')->all())
|
||||
->where('user_id', $user->id)
|
||||
->update(['liked' => false]);
|
||||
|
||||
event(new MultipleSongsUnliked($songs, $user));
|
||||
event(new MultipleSongsUnliked($playables, $user));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@ use App\Services\Contracts\MusicEncyclopedia;
|
|||
use App\Values\AlbumInformation;
|
||||
use App\Values\ArtistInformation;
|
||||
use Generator;
|
||||
use Illuminate\Cache\Repository as Cache;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class LastfmService implements MusicEncyclopedia
|
||||
{
|
||||
public function __construct(private readonly LastfmConnector $connector, private readonly Cache $cache)
|
||||
public function __construct(private readonly LastfmConnector $connector)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ class LastfmService implements MusicEncyclopedia
|
|||
}
|
||||
|
||||
return attempt_if(static::enabled(), function () use ($artist): ?ArtistInformation {
|
||||
return $this->cache->remember(
|
||||
return Cache::remember(
|
||||
"lastfm.artist.$artist->id",
|
||||
now()->addWeek(),
|
||||
fn () => $this->connector->send(new GetArtistInfoRequest($artist))->dto()
|
||||
|
@ -64,7 +64,7 @@ class LastfmService implements MusicEncyclopedia
|
|||
}
|
||||
|
||||
return attempt_if(static::enabled(), function () use ($album): ?AlbumInformation {
|
||||
return $this->cache->remember(
|
||||
return Cache::remember(
|
||||
"lastfm.album.$album->id",
|
||||
now()->addWeek(),
|
||||
fn () => $this->connector->send(new GetAlbumInfoRequest($album))->dto()
|
||||
|
|
|
@ -7,14 +7,13 @@ use App\Models\Artist;
|
|||
use App\Services\Contracts\MusicEncyclopedia;
|
||||
use App\Values\AlbumInformation;
|
||||
use App\Values\ArtistInformation;
|
||||
use Illuminate\Cache\Repository as Cache;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class MediaInformationService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MusicEncyclopedia $encyclopedia,
|
||||
private readonly MediaMetadataService $mediaMetadataService,
|
||||
private readonly Cache $cache
|
||||
private readonly MediaMetadataService $mediaMetadataService
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -24,20 +23,16 @@ class MediaInformationService
|
|||
return null;
|
||||
}
|
||||
|
||||
if ($this->cache->has('album.info.' . $album->id)) {
|
||||
return $this->cache->get('album.info.' . $album->id);
|
||||
}
|
||||
return Cache::remember("album.info.$album->id", now()->addWeek(), function () use ($album): AlbumInformation {
|
||||
$info = $this->encyclopedia->getAlbumInformation($album) ?: AlbumInformation::make();
|
||||
|
||||
$info = $this->encyclopedia->getAlbumInformation($album) ?: AlbumInformation::make();
|
||||
attempt_unless($album->has_cover, function () use ($info, $album): void {
|
||||
$this->mediaMetadataService->tryDownloadAlbumCover($album);
|
||||
$info->cover = $album->cover;
|
||||
});
|
||||
|
||||
attempt_unless($album->has_cover, function () use ($info, $album): void {
|
||||
$this->mediaMetadataService->tryDownloadAlbumCover($album);
|
||||
$info->cover = $album->cover;
|
||||
return $info;
|
||||
});
|
||||
|
||||
$this->cache->put('album.info.' . $album->id, $info, now()->addWeek());
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
public function getArtistInformation(Artist $artist): ?ArtistInformation
|
||||
|
@ -46,19 +41,19 @@ class MediaInformationService
|
|||
return null;
|
||||
}
|
||||
|
||||
if ($this->cache->has('artist.info.' . $artist->id)) {
|
||||
return $this->cache->get('artist.info.' . $artist->id);
|
||||
}
|
||||
return Cache::remember(
|
||||
"artist.info.$artist->id",
|
||||
now()->addWeek(),
|
||||
function () use ($artist): ArtistInformation {
|
||||
$info = $this->encyclopedia->getArtistInformation($artist) ?: ArtistInformation::make();
|
||||
|
||||
$info = $this->encyclopedia->getArtistInformation($artist) ?: ArtistInformation::make();
|
||||
attempt_unless($artist->has_image, function () use ($artist, $info): void {
|
||||
$this->mediaMetadataService->tryDownloadArtistImage($artist);
|
||||
$info->image = $artist->image;
|
||||
});
|
||||
|
||||
attempt_unless($artist->has_image, function () use ($artist, $info): void {
|
||||
$this->mediaMetadataService->tryDownloadArtistImage($artist);
|
||||
$info->image = $artist->image;
|
||||
});
|
||||
|
||||
$this->cache->put('artist.info.' . $artist->id, $info, now()->addWeek());
|
||||
|
||||
return $info;
|
||||
return $info;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use App\Values\ScanConfiguration;
|
|||
use App\Values\ScanResult;
|
||||
use App\Values\ScanResultCollection;
|
||||
use App\Values\WatchRecord\Contracts\WatchRecordInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use SplFileInfo;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Throwable;
|
||||
|
@ -25,8 +25,7 @@ class MediaScanner
|
|||
private readonly SettingRepository $settingRepository,
|
||||
private readonly SongRepository $songRepository,
|
||||
private readonly FileScanner $fileScanner,
|
||||
private readonly Finder $finder,
|
||||
private readonly LoggerInterface $logger
|
||||
private readonly Finder $finder
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -88,7 +87,7 @@ class MediaScanner
|
|||
|
||||
public function scanWatchRecord(WatchRecordInterface $record, ScanConfiguration $config): void
|
||||
{
|
||||
$this->logger->info("New watch record received: '{$record->getPath()}'");
|
||||
Log::info("New watch record received: '{$record->getPath()}'");
|
||||
|
||||
if ($record->isFile()) {
|
||||
$this->scanFileRecord($record, $config);
|
||||
|
@ -100,7 +99,7 @@ class MediaScanner
|
|||
private function scanFileRecord(WatchRecordInterface $record, ScanConfiguration $config): void
|
||||
{
|
||||
$path = $record->getPath();
|
||||
$this->logger->info("'$path' is a file.");
|
||||
Log::info("'$path' is a file.");
|
||||
|
||||
if ($record->isDeleted()) {
|
||||
$this->handleDeletedFileRecord($path);
|
||||
|
@ -112,7 +111,7 @@ class MediaScanner
|
|||
private function scanDirectoryRecord(WatchRecordInterface $record, ScanConfiguration $config): void
|
||||
{
|
||||
$path = $record->getPath();
|
||||
$this->logger->info("'$path' is a directory.");
|
||||
Log::info("'$path' is a directory.");
|
||||
|
||||
if ($record->isDeleted()) {
|
||||
$this->handleDeletedDirectoryRecord($path);
|
||||
|
@ -138,9 +137,9 @@ class MediaScanner
|
|||
|
||||
if ($song) {
|
||||
$song->delete();
|
||||
$this->logger->info("$path deleted.");
|
||||
Log::info("$path deleted.");
|
||||
} else {
|
||||
$this->logger->info("$path doesn't exist in our database--skipping.");
|
||||
Log::info("$path doesn't exist in our database--skipping.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,9 +148,9 @@ class MediaScanner
|
|||
$result = $this->fileScanner->setFile($path)->scan($config);
|
||||
|
||||
if ($result->isSuccess()) {
|
||||
$this->logger->info("Scanned $path");
|
||||
Log::info("Scanned $path");
|
||||
} else {
|
||||
$this->logger->info("Failed to scan $path. Maybe an invalid file?");
|
||||
Log::info("Failed to scan $path. Maybe an invalid file?");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,9 +159,9 @@ class MediaScanner
|
|||
$count = Song::query()->inDirectory($path)->delete();
|
||||
|
||||
if ($count) {
|
||||
$this->logger->info("Deleted $count song(s) under $path");
|
||||
Log::info("Deleted $count song(s) under $path");
|
||||
} else {
|
||||
$this->logger->info("$path is empty--no action needed.");
|
||||
Log::info("$path is empty--no action needed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,7 +177,7 @@ class MediaScanner
|
|||
}
|
||||
}
|
||||
|
||||
$this->logger->info("Scanned all song(s) under $path");
|
||||
Log::info("Scanned all song(s) under $path");
|
||||
|
||||
event(new MediaScanCompleted($scanResults));
|
||||
}
|
||||
|
|
|
@ -12,15 +12,14 @@ use App\Values\SongUpdateData;
|
|||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Throwable;
|
||||
|
||||
class SongService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly SongRepository $songRepository,
|
||||
private readonly SongStorage $songStorage,
|
||||
private readonly LoggerInterface $logger
|
||||
private readonly SongStorage $songStorage
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -40,12 +39,10 @@ class SongService
|
|||
|
||||
return DB::transaction(function () use ($ids, $data): Collection {
|
||||
return collect($ids)->reduce(function (Collection $updated, string $id) use ($data): Collection {
|
||||
/** @var Song|null $song */
|
||||
$song = Song::with('album', 'album.artist', 'artist')->find($id);
|
||||
|
||||
if ($song) {
|
||||
$updated->push($this->updateSong($song, clone $data));
|
||||
}
|
||||
optional(
|
||||
Song::query()->with('album.artist')->find($id),
|
||||
fn (Song $song) => $updated->push($this->updateSong($song, clone $data))
|
||||
);
|
||||
|
||||
return $updated;
|
||||
}, collect());
|
||||
|
@ -95,9 +92,9 @@ class SongService
|
|||
public function markSongsAsPrivate(Collection $songs): array
|
||||
{
|
||||
if (License::isPlus()) {
|
||||
// Songs that are in collaborative playlists can't be marked as private.
|
||||
/**
|
||||
* @var Collection<array-key, Song> $collaborativeSongs
|
||||
* Songs that are in collaborative playlists and can't be marked as private as a result
|
||||
*/
|
||||
$collaborativeSongs = Song::query()
|
||||
->whereIn('songs.id', $songs->pluck('id'))
|
||||
|
@ -124,11 +121,9 @@ class SongService
|
|||
public function deleteSongs(array|string $ids): void
|
||||
{
|
||||
$ids = Arr::wrap($ids);
|
||||
$shouldBackUp = config('koel.backup_on_delete');
|
||||
|
||||
DB::transaction(function () use ($ids): void {
|
||||
$shouldBackUp = config('koel.backup_on_delete');
|
||||
|
||||
/** @var Collection<array-key, Song> $songs */
|
||||
DB::transaction(function () use ($ids, $shouldBackUp): void {
|
||||
$songs = Song::query()->findMany($ids);
|
||||
|
||||
Song::destroy($ids);
|
||||
|
@ -137,7 +132,7 @@ class SongService
|
|||
try {
|
||||
$this->songStorage->delete($song, $shouldBackUp);
|
||||
} catch (Throwable $e) {
|
||||
$this->logger->error('Failed to remove song file', [
|
||||
Log::error('Failed to remove song file', [
|
||||
'path' => $song->path,
|
||||
'exception' => $e,
|
||||
]);
|
||||
|
|
|
@ -4,16 +4,12 @@ namespace App\Services;
|
|||
|
||||
use App\Models\User;
|
||||
use App\Values\CompositeToken;
|
||||
use Illuminate\Cache\Repository as Cache;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Laravel\Sanctum\NewAccessToken;
|
||||
use Laravel\Sanctum\PersonalAccessToken;
|
||||
|
||||
class TokenManager
|
||||
{
|
||||
public function __construct(private readonly Cache $cache)
|
||||
{
|
||||
}
|
||||
|
||||
public function createToken(User $user, array $abilities = ['*']): NewAccessToken
|
||||
{
|
||||
return $user->createToken(config('app.name'), $abilities);
|
||||
|
@ -26,7 +22,7 @@ class TokenManager
|
|||
audio: $this->createToken($user, ['audio'])
|
||||
);
|
||||
|
||||
$this->cache->rememberForever("app.composite-tokens.$token->apiToken", static fn () => $token->audioToken);
|
||||
Cache::forever("app.composite-tokens.$token->apiToken", $token->audioToken);
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
@ -34,11 +30,11 @@ class TokenManager
|
|||
public function deleteCompositionToken(string $plainTextApiToken): void
|
||||
{
|
||||
/** @var string $audioToken */
|
||||
$audioToken = $this->cache->get("app.composite-tokens.$plainTextApiToken");
|
||||
$audioToken = Cache::get("app.composite-tokens.$plainTextApiToken");
|
||||
|
||||
if ($audioToken) {
|
||||
self::deleteTokenByPlainTextToken($audioToken);
|
||||
$this->cache->forget("app.composite-tokens.$plainTextApiToken");
|
||||
Cache::forget("app.composite-tokens.$plainTextApiToken");
|
||||
}
|
||||
|
||||
self::deleteTokenByPlainTextToken($plainTextApiToken);
|
||||
|
|
|
@ -6,15 +6,15 @@ use App\Exceptions\InvitationNotFoundException;
|
|||
use App\Mail\UserInvite;
|
||||
use App\Models\User;
|
||||
use App\Repositories\UserRepository;
|
||||
use Illuminate\Contracts\Hashing\Hasher as Hash;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UserInvitationService
|
||||
{
|
||||
public function __construct(private readonly Hash $hash, private readonly UserRepository $userRepository)
|
||||
public function __construct(private readonly UserRepository $userRepository)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -26,15 +26,13 @@ class UserInvitationService
|
|||
});
|
||||
}
|
||||
|
||||
/** @throws InvitationNotFoundException */
|
||||
public function getUserProspectByToken(string $token): User
|
||||
{
|
||||
return User::query()->where('invitation_token', $token)->firstOr(static function (): void {
|
||||
return User::query()->where('invitation_token', $token)->firstOr(static function (): never {
|
||||
throw new InvitationNotFoundException();
|
||||
});
|
||||
}
|
||||
|
||||
/** @throws InvitationNotFoundException */
|
||||
public function revokeByEmail(string $email): void
|
||||
{
|
||||
$user = $this->userRepository->findOneByEmail($email);
|
||||
|
@ -59,14 +57,13 @@ class UserInvitationService
|
|||
return $invitee;
|
||||
}
|
||||
|
||||
/** @throws InvitationNotFoundException */
|
||||
public function accept(string $token, string $name, string $password): User
|
||||
{
|
||||
$user = $this->getUserProspectByToken($token);
|
||||
|
||||
$user->update([
|
||||
$user->update(attributes: [
|
||||
'name' => $name,
|
||||
'password' => $this->hash->make($password),
|
||||
'password' => Hash::make($password),
|
||||
'invitation_token' => null,
|
||||
'invitation_accepted_at' => now(),
|
||||
]);
|
||||
|
|
|
@ -7,20 +7,16 @@ use App\Facades\License;
|
|||
use App\Models\User;
|
||||
use App\Repositories\UserRepository;
|
||||
use App\Values\SSOUser;
|
||||
use Illuminate\Contracts\Hashing\Hasher;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UserService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserRepository $repository,
|
||||
private readonly Hasher $hash,
|
||||
private readonly ImageWriter $imageWriter
|
||||
) {
|
||||
public function __construct(private readonly UserRepository $repository, private readonly ImageWriter $imageWriter)
|
||||
{
|
||||
}
|
||||
|
||||
/** @noinspection PhpIncompatibleReturnTypeInspection */
|
||||
public function createUser(
|
||||
string $name,
|
||||
string $email,
|
||||
|
@ -38,7 +34,7 @@ class UserService
|
|||
return User::query()->create([
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'password' => $plainTextPassword ? $this->hash->make($plainTextPassword) : '',
|
||||
'password' => $plainTextPassword ? Hash::make($plainTextPassword) : '',
|
||||
'is_admin' => $isAdmin,
|
||||
'sso_id' => $ssoId,
|
||||
'sso_provider' => $ssoProvider,
|
||||
|
@ -94,7 +90,7 @@ class UserService
|
|||
$user->update([
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'password' => $password ? $this->hash->make($password) : $user->password,
|
||||
'password' => $password ? Hash::make($password) : $user->password,
|
||||
'is_admin' => $isAdmin ?? $user->is_admin,
|
||||
'avatar' => $avatar ? $this->createNewAvatar($avatar, $user) : null,
|
||||
]);
|
||||
|
|
|
@ -5,12 +5,12 @@ namespace App\Services;
|
|||
use App\Http\Integrations\YouTube\Requests\SearchVideosRequest;
|
||||
use App\Http\Integrations\YouTube\YouTubeConnector;
|
||||
use App\Models\Song;
|
||||
use Illuminate\Cache\Repository as Cache;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Throwable;
|
||||
|
||||
class YouTubeService
|
||||
{
|
||||
public function __construct(private readonly YouTubeConnector $connector, private readonly Cache $cache)
|
||||
public function __construct(private readonly YouTubeConnector $connector)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ class YouTubeService
|
|||
$hash = md5(serialize($request->query()->all()));
|
||||
|
||||
try {
|
||||
return $this->cache->remember(
|
||||
return Cache::remember(
|
||||
"youtube.$hash",
|
||||
now()->addWeek(),
|
||||
fn () => $this->connector->send($request)->object()
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace App\Values;
|
|||
|
||||
use App\Models\Album;
|
||||
use App\Models\Artist;
|
||||
use App\Services\Helper;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
|
@ -71,7 +70,7 @@ final class SongScanInformation implements Arrayable
|
|||
length: (float) Arr::get($info, 'playtime_seconds'),
|
||||
cover: $cover,
|
||||
path: $path,
|
||||
mTime: Helper::getModifiedTime($path)
|
||||
mTime: get_mtime($path)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ use GuzzleHttp\Client;
|
|||
use GuzzleHttp\Handler\MockHandler;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Contracts\Cache\Repository as Cache;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Tests\TestCase;
|
||||
|
||||
|
@ -24,7 +23,7 @@ class ApplicationInformationServiceTest extends TestCase
|
|||
]);
|
||||
|
||||
$client = new Client(['handler' => HandlerStack::create($mock)]);
|
||||
$service = new ApplicationInformationService($client, app(Cache::class));
|
||||
$service = new ApplicationInformationService($client);
|
||||
|
||||
self::assertSame($latestVersion, $service->getLatestVersionNumber());
|
||||
self::assertSame($latestVersion, cache()->get('latestKoelVersion'));
|
||||
|
|
|
@ -6,7 +6,6 @@ use App\Repositories\UserRepository;
|
|||
use App\Services\AuthenticationService;
|
||||
use App\Services\TokenManager;
|
||||
use Illuminate\Auth\Passwords\PasswordBroker;
|
||||
use Illuminate\Hashing\HashManager;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Mockery\MockInterface;
|
||||
use Tests\TestCase;
|
||||
|
@ -15,7 +14,6 @@ class AuthenticationServiceTest extends TestCase
|
|||
{
|
||||
private UserRepository|MockInterface $userRepository;
|
||||
private TokenManager|MockInterface $tokenManager;
|
||||
private HashManager|MockInterface $hash;
|
||||
private PasswordBroker|MockInterface $passwordBroker;
|
||||
private AuthenticationService $service;
|
||||
|
||||
|
@ -25,13 +23,11 @@ class AuthenticationServiceTest extends TestCase
|
|||
|
||||
$this->userRepository = $this->mock(UserRepository::class);
|
||||
$this->tokenManager = $this->mock(TokenManager::class);
|
||||
$this->hash = $this->mock(HashManager::class);
|
||||
$this->passwordBroker = $this->mock(PasswordBroker::class);
|
||||
|
||||
$this->service = new AuthenticationService(
|
||||
$this->userRepository,
|
||||
$this->tokenManager,
|
||||
$this->hash,
|
||||
$this->passwordBroker
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ use App\Services\MediaInformationService;
|
|||
use App\Services\MediaMetadataService;
|
||||
use App\Values\AlbumInformation;
|
||||
use App\Values\ArtistInformation;
|
||||
use Illuminate\Cache\Repository as Cache;
|
||||
use Mockery;
|
||||
use Mockery\LegacyMockInterface;
|
||||
use Mockery\MockInterface;
|
||||
|
@ -29,11 +28,7 @@ class MediaInformationServiceTest extends TestCase
|
|||
$this->encyclopedia = Mockery::mock(LastfmService::class);
|
||||
$this->mediaMetadataService = Mockery::mock(MediaMetadataService::class);
|
||||
|
||||
$this->mediaInformationService = new MediaInformationService(
|
||||
$this->encyclopedia,
|
||||
$this->mediaMetadataService,
|
||||
app(Cache::class)
|
||||
);
|
||||
$this->mediaInformationService = new MediaInformationService($this->encyclopedia, $this->mediaMetadataService);
|
||||
}
|
||||
|
||||
public function testGetAlbumInformation(): void
|
||||
|
|
Loading…
Reference in a new issue