mirror of
https://github.com/koel/koel
synced 2024-11-10 06:34:14 +00:00
fix(build): fixing build errors
This commit is contained in:
parent
781af8dc27
commit
e3086422c7
14 changed files with 40 additions and 39 deletions
|
@ -8,12 +8,15 @@ use App\Models\Song;
|
||||||
use App\Repositories\SongRepository;
|
use App\Repositories\SongRepository;
|
||||||
use App\Services\DownloadService;
|
use App\Services\DownloadService;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class DownloadSongsController extends Controller
|
class DownloadSongsController extends Controller
|
||||||
{
|
{
|
||||||
public function __invoke(DownloadSongsRequest $request, DownloadService $service, SongRepository $repository)
|
public function __invoke(DownloadSongsRequest $request, DownloadService $service, SongRepository $repository)
|
||||||
{
|
{
|
||||||
// Don't use SongRepository::findMany() because it'd have been already catered to the current user.
|
// Don't use SongRepository::findMany() because it'd have been already catered to the current user.
|
||||||
|
|
||||||
|
/** @var Array<Song>|Collection<array-key, Song> $songs */
|
||||||
$songs = Song::query()->findMany($request->songs);
|
$songs = Song::query()->findMany($request->songs);
|
||||||
$songs->each(fn ($song) => $this->authorize('download', $song));
|
$songs->each(fn ($song) => $this->authorize('download', $song));
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ use PhanAn\Poddle\Values\CategoryCollection;
|
||||||
use PhanAn\Poddle\Values\ChannelMetadata;
|
use PhanAn\Poddle\Values\ChannelMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property-read string $id
|
* @property string $id
|
||||||
* @property string $url
|
* @property string $url
|
||||||
* @property string $title
|
* @property string $title
|
||||||
* @property string $description
|
* @property string $description
|
||||||
|
|
|
@ -17,6 +17,7 @@ use App\Values\SongStorageMetadata\S3LambdaMetadata;
|
||||||
use App\Values\SongStorageMetadata\SftpMetadata;
|
use App\Values\SongStorageMetadata\SftpMetadata;
|
||||||
use App\Values\SongStorageMetadata\SongStorageMetadata;
|
use App\Values\SongStorageMetadata\SongStorageMetadata;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
@ -31,7 +32,7 @@ use Throwable;
|
||||||
/**
|
/**
|
||||||
* @property string $path
|
* @property string $path
|
||||||
* @property string $title
|
* @property string $title
|
||||||
* @property Album $album
|
* @property ?Album $album
|
||||||
* @property User $uploader
|
* @property User $uploader
|
||||||
* @property ?Artist $artist
|
* @property ?Artist $artist
|
||||||
* @property ?Artist $album_artist
|
* @property ?Artist $album_artist
|
||||||
|
@ -105,13 +106,12 @@ class Song extends Model
|
||||||
public static function query(?PlayableType $type = null, ?User $user = null): SongBuilder
|
public static function query(?PlayableType $type = null, ?User $user = null): SongBuilder
|
||||||
{
|
{
|
||||||
return parent::query()
|
return parent::query()
|
||||||
->when($type, static function (SongBuilder $query) use ($type): void {
|
->when($type, static fn (Builder $query) => match ($type) { // @phpstan-ignore-line phpcs:ignore
|
||||||
match ($type) {
|
PlayableType::SONG => $query->whereNull('songs.podcast_id'),
|
||||||
PlayableType::SONG => $query->whereNull('songs.podcast_id'),
|
PlayableType::PODCAST_EPISODE => $query->whereNotNull('songs.podcast_id'),
|
||||||
PlayableType::PODCAST_EPISODE => $query->whereNotNull('songs.podcast_id'),
|
default => $query,
|
||||||
};
|
|
||||||
})
|
})
|
||||||
->when($user, static fn (SongBuilder $query) => $query->forUser($user));
|
->when($user, static fn (SongBuilder $query) => $query->forUser($user)); // @phpstan-ignore-line
|
||||||
}
|
}
|
||||||
|
|
||||||
public function owner(): BelongsTo
|
public function owner(): BelongsTo
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Policies;
|
|
||||||
|
|
||||||
use App\Models\Podcast\Song;
|
|
||||||
use App\Models\User;
|
|
||||||
|
|
||||||
class EpisodePolicy
|
|
||||||
{
|
|
||||||
public function access(User $user, Song $episode): bool
|
|
||||||
{
|
|
||||||
return $user->subscribedToPodcast($episode->podcast);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,8 +21,9 @@ use Throwable;
|
||||||
|
|
||||||
class LicenseService implements LicenseServiceInterface
|
class LicenseService implements LicenseServiceInterface
|
||||||
{
|
{
|
||||||
public function __construct(private readonly LemonSqueezyConnector $connector, private readonly string $hashSalt)
|
public function __construct(private readonly LemonSqueezyConnector $connector, private ?string $hashSalt = null)
|
||||||
{
|
{
|
||||||
|
$this->hashSalt ??= config('app.key');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function activate(string $key): License
|
public function activate(string $key): License
|
||||||
|
|
|
@ -13,6 +13,7 @@ use App\Repositories\SongRepository;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use GuzzleHttp\RedirectMiddleware;
|
use GuzzleHttp\RedirectMiddleware;
|
||||||
|
use GuzzleHttp\RequestOptions;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
|
@ -56,6 +57,7 @@ class PodcastService
|
||||||
$channel = $parser->getChannel();
|
$channel = $parser->getChannel();
|
||||||
|
|
||||||
return DB::transaction(function () use ($url, $podcast, $parser, $channel, $user) {
|
return DB::transaction(function () use ($url, $podcast, $parser, $channel, $user) {
|
||||||
|
/** @var Podcast $podcast */
|
||||||
$podcast = Podcast::query()->create([
|
$podcast = Podcast::query()->create([
|
||||||
'url' => $url,
|
'url' => $url,
|
||||||
'title' => $channel->title,
|
'title' => $channel->title,
|
||||||
|
@ -102,8 +104,8 @@ class PodcastService
|
||||||
'last_synced_at' => now(),
|
'last_synced_at' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$pubDate = $parser->xmlReader->value('rss.channel.pubDate')?->first()
|
$pubDate = $parser->xmlReader->value('rss.channel.pubDate')->first()
|
||||||
?? $parser->xmlReader->value('rss.channel.lastBuildDate')?->first();
|
?? $parser->xmlReader->value('rss.channel.lastBuildDate')->first();
|
||||||
|
|
||||||
if ($pubDate && Carbon::createFromFormat(Carbon::RFC1123, $pubDate)->isBefore($podcast->last_synced_at)) {
|
if ($pubDate && Carbon::createFromFormat(Carbon::RFC1123, $pubDate)->isBefore($podcast->last_synced_at)) {
|
||||||
// The pubDate/lastBuildDate value indicates that there's no new content since last check.
|
// The pubDate/lastBuildDate value indicates that there's no new content since last check.
|
||||||
|
@ -150,7 +152,7 @@ class PodcastService
|
||||||
|
|
||||||
// Since insert() doesn't trigger model events, Scout operations will not be called.
|
// Since insert() doesn't trigger model events, Scout operations will not be called.
|
||||||
// We have to manually update the search index.
|
// We have to manually update the search index.
|
||||||
Episode::query()->whereIn('id', $ids)->searchable();
|
Episode::query()->whereIn('id', $ids)->searchable(); // @phpstan-ignore-line
|
||||||
}
|
}
|
||||||
|
|
||||||
private function subscribeUserToPodcast(User $user, Podcast $podcast): void
|
private function subscribeUserToPodcast(User $user, Podcast $podcast): void
|
||||||
|
@ -206,16 +208,16 @@ class PodcastService
|
||||||
$url = $url->path;
|
$url = $url->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
$client ??= $this->client ?? new Client();
|
$client ??= new Client();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $client->request($method, $url, [
|
$response = $client->request($method, $url, [
|
||||||
'headers' => [
|
RequestOptions::HEADERS => [
|
||||||
'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.15', // @phpcs-ignore-line
|
'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.15', // @phpcs-ignore-line
|
||||||
'Origin' => '*',
|
'Origin' => '*',
|
||||||
],
|
],
|
||||||
'http_errors' => false,
|
RequestOptions::HTTP_ERRORS => false,
|
||||||
'allow_redirects' => ['track_redirects' => true],
|
RequestOptions::ALLOW_REDIRECTS => ['track_redirects' => true],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$redirects = Arr::wrap($response->getHeader(RedirectMiddleware::HISTORY_HEADER));
|
$redirects = Arr::wrap($response->getHeader(RedirectMiddleware::HISTORY_HEADER));
|
||||||
|
|
|
@ -52,7 +52,7 @@ class SearchService
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return $repository->getMany(
|
return $repository->getMany(
|
||||||
ids: $repository->model::search($keywords)->get()->take($count)->pluck('id')->all(),
|
ids: $repository->model::search($keywords)->get()->take($count)->pluck('id')->all(), // @phpstan-ignore-line
|
||||||
preserveOrder: true,
|
preserveOrder: true,
|
||||||
);
|
);
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
|
|
|
@ -41,7 +41,7 @@ class SongService
|
||||||
return collect($ids)->reduce(function (Collection $updated, string $id) use ($data): Collection {
|
return collect($ids)->reduce(function (Collection $updated, string $id) use ($data): Collection {
|
||||||
optional(
|
optional(
|
||||||
Song::query()->with('album.artist')->find($id),
|
Song::query()->with('album.artist')->find($id),
|
||||||
fn (Song $song) => $updated->push($this->updateSong($song, clone $data))
|
fn (Song $song) => $updated->push($this->updateSong($song, clone $data)) // @phpstan-ignore-line
|
||||||
);
|
);
|
||||||
|
|
||||||
return $updated;
|
return $updated;
|
||||||
|
|
|
@ -29,6 +29,7 @@ parameters:
|
||||||
- '#Method App\\Models\\.*::query\(\) should return App\\Builders\\.*Builder but returns Illuminate\\Database\\Eloquent\\Builder<Illuminate\\Database\\Eloquent\\Model>#'
|
- '#Method App\\Models\\.*::query\(\) should return App\\Builders\\.*Builder but returns Illuminate\\Database\\Eloquent\\Builder<Illuminate\\Database\\Eloquent\\Model>#'
|
||||||
- '#Parameter \#1 \$callback of method Illuminate\\Support\\Collection<int,Illuminate\\Database\\Eloquent\\Model>::each\(\) expects callable\(Illuminate\\Database\\Eloquent\\Model, int\)#'
|
- '#Parameter \#1 \$callback of method Illuminate\\Support\\Collection<int,Illuminate\\Database\\Eloquent\\Model>::each\(\) expects callable\(Illuminate\\Database\\Eloquent\\Model, int\)#'
|
||||||
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::#'
|
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::#'
|
||||||
|
- '#Unknown parameter \$(type|user) in call to static method App\\Models\\Song::query\(\)#'
|
||||||
|
|
||||||
|
|
||||||
excludePaths:
|
excludePaths:
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Broadcast;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Broadcast Channels
|
| Broadcast Channels
|
||||||
|
@ -12,4 +10,3 @@ use Illuminate\Support\Facades\Broadcast;
|
||||||
| used to check if an authenticated user can listen to the channel.
|
| used to check if an authenticated user can listen to the channel.
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
Broadcast::channel('App.User.{id}', static fn ($user, $id) => (int) $user->id === (int) $id);
|
|
||||||
|
|
|
@ -28,7 +28,9 @@ class ExcerptSearchTest extends TestCase
|
||||||
Album::factory(4)->create();
|
Album::factory(4)->create();
|
||||||
|
|
||||||
$user = create_user();
|
$user = create_user();
|
||||||
$user->subscribeToPodcast(Podcast::factory()->create(['title' => 'Foo Podcast']));
|
/** @var Podcast $podcast */
|
||||||
|
$podcast = Podcast::factory()->create(['title' => 'Foo Podcast']);
|
||||||
|
$user->subscribeToPodcast($podcast);
|
||||||
|
|
||||||
$this->getAs('api/search?q=foo', $user)
|
$this->getAs('api/search?q=foo', $user)
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
|
|
|
@ -212,6 +212,7 @@ class PlaylistServiceTest extends TestCase
|
||||||
$playlist = Playlist::factory()->create();
|
$playlist = Playlist::factory()->create();
|
||||||
$playlist->addPlayables(Song::factory(3)->create());
|
$playlist->addPlayables(Song::factory(3)->create());
|
||||||
|
|
||||||
|
/** @var Podcast $podcast */
|
||||||
$podcast = Podcast::factory()->create();
|
$podcast = Podcast::factory()->create();
|
||||||
$episodes = Song::factory(2)->asEpisode()->for($podcast)->create();
|
$episodes = Song::factory(2)->asEpisode()->for($podcast)->create();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Integration\Services;
|
namespace Tests\Integration\Services;
|
||||||
|
|
||||||
use App\Exceptions\UserAlreadySubscribedToPodcast;
|
use App\Exceptions\UserAlreadySubscribedToPodcast;
|
||||||
use App\Models\Podcast;
|
use App\Models\Podcast;
|
||||||
|
@ -8,11 +8,11 @@ use App\Models\PodcastUserPivot;
|
||||||
use App\Models\Song;
|
use App\Models\Song;
|
||||||
use App\Services\PodcastService;
|
use App\Services\PodcastService;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\ClientInterface;
|
||||||
use GuzzleHttp\Handler\MockHandler;
|
use GuzzleHttp\Handler\MockHandler;
|
||||||
use GuzzleHttp\HandlerStack;
|
use GuzzleHttp\HandlerStack;
|
||||||
use GuzzleHttp\Psr7\Response;
|
use GuzzleHttp\Psr7\Response;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Psr\Http\Client\ClientInterface;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
use function Tests\create_user;
|
use function Tests\create_user;
|
||||||
|
@ -59,6 +59,7 @@ class PodcastServiceTest extends TestCase
|
||||||
|
|
||||||
public function testSubscribeUserToPodcast(): void
|
public function testSubscribeUserToPodcast(): void
|
||||||
{
|
{
|
||||||
|
/** @var Podcast $podcast */
|
||||||
$podcast = Podcast::factory()->create([
|
$podcast = Podcast::factory()->create([
|
||||||
'url' => 'https://example.com/feed.xml',
|
'url' => 'https://example.com/feed.xml',
|
||||||
'title' => 'My Cool Podcast',
|
'title' => 'My Cool Podcast',
|
||||||
|
@ -79,6 +80,7 @@ class PodcastServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
self::expectException(UserAlreadySubscribedToPodcast::class);
|
self::expectException(UserAlreadySubscribedToPodcast::class);
|
||||||
|
|
||||||
|
/** @var Podcast $podcast */
|
||||||
$podcast = Podcast::factory()->create([
|
$podcast = Podcast::factory()->create([
|
||||||
'url' => 'https://example.com/feed.xml',
|
'url' => 'https://example.com/feed.xml',
|
||||||
]);
|
]);
|
||||||
|
@ -97,6 +99,7 @@ class PodcastServiceTest extends TestCase
|
||||||
'https://example.com/feed.xml' => Http::response(headers: ['Last-Modified' => now()->toRfc1123String()]),
|
'https://example.com/feed.xml' => Http::response(headers: ['Last-Modified' => now()->toRfc1123String()]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
/** @var Podcast $podcast */
|
||||||
$podcast = Podcast::factory()->create([
|
$podcast = Podcast::factory()->create([
|
||||||
'url' => 'https://example.com/feed.xml',
|
'url' => 'https://example.com/feed.xml',
|
||||||
'title' => 'Shall be changed very sad',
|
'title' => 'Shall be changed very sad',
|
||||||
|
@ -116,6 +119,7 @@ class PodcastServiceTest extends TestCase
|
||||||
|
|
||||||
public function testUnsubscribeUserFromPodcast(): void
|
public function testUnsubscribeUserFromPodcast(): void
|
||||||
{
|
{
|
||||||
|
/** @var Podcast $podcast */
|
||||||
$podcast = Podcast::factory()->create();
|
$podcast = Podcast::factory()->create();
|
||||||
$user = create_user();
|
$user = create_user();
|
||||||
$user->subscribeToPodcast($podcast);
|
$user->subscribeToPodcast($podcast);
|
||||||
|
@ -127,6 +131,7 @@ class PodcastServiceTest extends TestCase
|
||||||
|
|
||||||
public function testPodcastNotObsoleteIfSyncedRecently(): void
|
public function testPodcastNotObsoleteIfSyncedRecently(): void
|
||||||
{
|
{
|
||||||
|
/** @var Podcast $podcast */
|
||||||
$podcast = Podcast::factory()->create([
|
$podcast = Podcast::factory()->create([
|
||||||
'last_synced_at' => now()->subHours(6),
|
'last_synced_at' => now()->subHours(6),
|
||||||
]);
|
]);
|
||||||
|
@ -140,6 +145,7 @@ class PodcastServiceTest extends TestCase
|
||||||
'https://example.com/feed.xml' => Http::response(headers: ['Last-Modified' => now()->toRfc1123String()]),
|
'https://example.com/feed.xml' => Http::response(headers: ['Last-Modified' => now()->toRfc1123String()]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
/** @var Podcast $podcast */
|
||||||
$podcast = Podcast::factory()->create([
|
$podcast = Podcast::factory()->create([
|
||||||
'url' => 'https://example.com/feed.xml',
|
'url' => 'https://example.com/feed.xml',
|
||||||
'last_synced_at' => now()->subDays(1),
|
'last_synced_at' => now()->subDays(1),
|
||||||
|
@ -150,6 +156,7 @@ class PodcastServiceTest extends TestCase
|
||||||
|
|
||||||
public function testUpdateEpisodeProgress(): void
|
public function testUpdateEpisodeProgress(): void
|
||||||
{
|
{
|
||||||
|
/** @var Song $episode */
|
||||||
$episode = Song::factory()->asEpisode()->create();
|
$episode = Song::factory()->asEpisode()->create();
|
||||||
$user = create_user();
|
$user = create_user();
|
||||||
$user->subscribeToPodcast($episode->podcast);
|
$user->subscribeToPodcast($episode->podcast);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Integration\Values;
|
namespace Tests\Integration\Values;
|
||||||
|
|
||||||
use App\Models\Song;
|
use App\Models\Song;
|
||||||
use App\Values\Podcast\EpisodePlayable;
|
use App\Values\Podcast\EpisodePlayable;
|
||||||
|
@ -16,6 +16,7 @@ class EpisodePlayableTest extends TestCase
|
||||||
'https://example.com/episode.mp3' => Http::response('foo'),
|
'https://example.com/episode.mp3' => Http::response('foo'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
/** @var Song $episode */
|
||||||
$episode = Song::factory()->asEpisode()->create([
|
$episode = Song::factory()->asEpisode()->create([
|
||||||
'path' => 'https://example.com/episode.mp3',
|
'path' => 'https://example.com/episode.mp3',
|
||||||
]);
|
]);
|
||||||
|
|
Loading…
Reference in a new issue