mirror of
https://github.com/AnimeThemes/animethemes-server.git
synced 2026-07-11 01:24:46 +02:00
refactor(graphql): remove resolver classes (#1176)
This commit is contained in:
@@ -1,96 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Resolvers;
|
||||
|
||||
use App\GraphQL\Schema\Mutations\BaseMutation;
|
||||
use Illuminate\Pipeline\Pipeline;
|
||||
use Illuminate\Routing\ControllerMiddlewareOptions;
|
||||
use Illuminate\Routing\FiltersControllerMiddleware;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
abstract class BaseResolver
|
||||
{
|
||||
final public const MODEL = 'model';
|
||||
|
||||
/**
|
||||
* HTTP middleware stack that should be run before the resolver action.
|
||||
*
|
||||
* Each element is an array with keys `middleware` and `options`. The
|
||||
* `options` array is the same structure that the `ControllerMiddlewareOptions`
|
||||
* helper understands (see `only` / `except`). This mirrors the behaviour of
|
||||
* Laravel controllers so you can register middleware exactly the same way:
|
||||
*
|
||||
* $this->middleware('auth')->only('store');
|
||||
* $this->middleware(['auth', 'log'])->except('destroy');
|
||||
*
|
||||
* The resolver will evaluate the options against the current action name
|
||||
* when deciding which middleware to run.
|
||||
*
|
||||
* @var array<int, array{middleware:class-string|string,options:array}>
|
||||
*/
|
||||
protected array $middleware = [];
|
||||
|
||||
/**
|
||||
* Get the attributes and values that were validated.
|
||||
*
|
||||
* @param class-string<BaseMutation> $mutation
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function validated(array $args, string $mutation): array
|
||||
{
|
||||
$mutationInstance = App::make($mutation);
|
||||
|
||||
$validator = Validator::make($args, $mutationInstance->rulesForValidation($args));
|
||||
|
||||
return $validator->validated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the middleware pipeline for the given action.
|
||||
*/
|
||||
protected function runMiddleware(): void
|
||||
{
|
||||
$action = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];
|
||||
|
||||
$stack = [];
|
||||
foreach ($this->middleware as $entry) {
|
||||
$options = $entry['options'] ?? [];
|
||||
|
||||
if (FiltersControllerMiddleware::methodExcludedByOptions($action, $options)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$stack[] = $entry['middleware'];
|
||||
}
|
||||
|
||||
if ($stack === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(Pipeline::class)
|
||||
->send(request())
|
||||
->through($stack)
|
||||
->thenReturn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register middleware on the controller.
|
||||
*
|
||||
* @param \Closure|array|string $middleware
|
||||
* @return ControllerMiddlewareOptions
|
||||
*/
|
||||
public function middleware($middleware, array $options = [])
|
||||
{
|
||||
foreach ((array) $middleware as $m) {
|
||||
$this->middleware[] = [
|
||||
'middleware' => $m,
|
||||
'options' => &$options,
|
||||
];
|
||||
}
|
||||
|
||||
return new ControllerMiddlewareOptions($options);
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Resolvers\List\Playlist;
|
||||
|
||||
use App\Actions\Http\Api\List\Playlist\Track\DestroyTrackAction;
|
||||
use App\Actions\Http\Api\List\Playlist\Track\StoreTrackAction;
|
||||
use App\Actions\Http\Api\List\Playlist\Track\UpdateTrackAction;
|
||||
use App\Features\AllowPlaylistManagement;
|
||||
use App\GraphQL\Resolvers\BaseResolver;
|
||||
use App\GraphQL\Schema\Mutations\Models\List\Playlist\Track\CreatePlaylistTrackMutation;
|
||||
use App\GraphQL\Schema\Mutations\Models\List\Playlist\Track\UpdatePlaylistTrackMutation;
|
||||
use App\Http\Middleware\Models\List\PlaylistExceedsTrackLimit;
|
||||
use App\Models\List\Playlist;
|
||||
use App\Models\List\Playlist\PlaylistTrack;
|
||||
use Illuminate\Support\Arr;
|
||||
use Laravel\Pennant\Middleware\EnsureFeaturesAreActive;
|
||||
|
||||
class PlaylistTrackResolver extends BaseResolver
|
||||
{
|
||||
final public const string ATTRIBUTE_ENTRY = 'entryId';
|
||||
final public const string ATTRIBUTE_VIDEO = 'videoId';
|
||||
|
||||
public static Playlist $playlist;
|
||||
|
||||
public function __construct(Playlist $playlist)
|
||||
{
|
||||
static::$playlist = $playlist;
|
||||
|
||||
$this->middleware(EnsureFeaturesAreActive::using(AllowPlaylistManagement::class))->only(['store', 'update', 'destroy']);
|
||||
$this->middleware(PlaylistExceedsTrackLimit::class)->only(['store']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function store(array $args, StoreTrackAction $action): PlaylistTrack
|
||||
{
|
||||
$this->runMiddleware();
|
||||
|
||||
/** @var Playlist $playlist */
|
||||
$playlist = Arr::get($args, 'playlist');
|
||||
|
||||
$validated = $this->validated($args, CreatePlaylistTrackMutation::class);
|
||||
|
||||
$validated = [
|
||||
PlaylistTrack::ATTRIBUTE_ENTRY => Arr::integer($validated, 'entryId'),
|
||||
PlaylistTrack::ATTRIBUTE_VIDEO => Arr::integer($validated, 'videoId'),
|
||||
];
|
||||
|
||||
return $action->store($playlist, PlaylistTrack::query(), $validated);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function update(array $args, UpdateTrackAction $action): PlaylistTrack
|
||||
{
|
||||
$this->runMiddleware();
|
||||
|
||||
/** @var PlaylistTrack $track */
|
||||
$track = Arr::get($args, self::MODEL);
|
||||
|
||||
$validated = $this->validated($args, UpdatePlaylistTrackMutation::class);
|
||||
|
||||
$validated = [
|
||||
PlaylistTrack::ATTRIBUTE_ENTRY => Arr::integer($validated, 'entryId'),
|
||||
PlaylistTrack::ATTRIBUTE_VIDEO => Arr::integer($validated, 'videoId'),
|
||||
];
|
||||
|
||||
return $action->update($track->playlist, $track, $validated);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function destroy(array $args, DestroyTrackAction $action): array
|
||||
{
|
||||
$this->runMiddleware();
|
||||
|
||||
/** @var PlaylistTrack $track */
|
||||
$track = Arr::get($args, self::MODEL);
|
||||
|
||||
$message = $action->destroy($track->playlist, $track);
|
||||
|
||||
return [
|
||||
'message' => $message,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Resolvers\List;
|
||||
|
||||
use App\Actions\Http\Api\DestroyAction;
|
||||
use App\Actions\Http\Api\StoreAction;
|
||||
use App\Actions\Http\Api\UpdateAction;
|
||||
use App\Features\AllowPlaylistManagement;
|
||||
use App\GraphQL\Resolvers\BaseResolver;
|
||||
use App\GraphQL\Schema\Mutations\Models\List\Playlist\CreatePlaylistMutation;
|
||||
use App\GraphQL\Schema\Mutations\Models\List\Playlist\UpdatePlaylistMutation;
|
||||
use App\Http\Middleware\Models\List\UserExceedsPlaylistLimit;
|
||||
use App\Models\List\Playlist;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Laravel\Pennant\Middleware\EnsureFeaturesAreActive;
|
||||
|
||||
class PlaylistResolver extends BaseResolver
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware(EnsureFeaturesAreActive::using(AllowPlaylistManagement::class))->only(['store', 'update', 'destroy']);
|
||||
$this->middleware(UserExceedsPlaylistLimit::class)->only(['store']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
* @param StoreAction<Playlist> $action
|
||||
*/
|
||||
public function store(array $args, StoreAction $action): Playlist
|
||||
{
|
||||
$this->runMiddleware();
|
||||
|
||||
$validated = $this->validated($args, CreatePlaylistMutation::class);
|
||||
|
||||
$parameters = [
|
||||
...$validated,
|
||||
Playlist::ATTRIBUTE_USER => Auth::id(),
|
||||
];
|
||||
|
||||
return $action->store(Playlist::query(), $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
* @param UpdateAction<Playlist> $action
|
||||
*/
|
||||
public function update(array $args, UpdateAction $action): Playlist
|
||||
{
|
||||
$this->runMiddleware();
|
||||
|
||||
/** @var Playlist $playlist */
|
||||
$playlist = Arr::pull($args, self::MODEL);
|
||||
|
||||
$validated = $this->validated($args, UpdatePlaylistMutation::class);
|
||||
|
||||
return $action->update($playlist, $validated);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
* @param DestroyAction<Playlist> $action
|
||||
*/
|
||||
public function destroy(array $args, DestroyAction $action): array
|
||||
{
|
||||
$this->runMiddleware();
|
||||
|
||||
/** @var Playlist $playlist */
|
||||
$playlist = Arr::get($args, self::MODEL);
|
||||
|
||||
$message = $action->forceDelete($playlist);
|
||||
|
||||
return [
|
||||
'message' => $message,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Resolvers\List;
|
||||
|
||||
use App\Exceptions\GraphQL\ClientForbiddenException;
|
||||
use App\Features\AllowExternalProfileManagement;
|
||||
use App\GraphQL\Resolvers\BaseResolver;
|
||||
use App\Http\Middleware\Api\EnabledOnlyOnLocalhost;
|
||||
use App\Models\List\ExternalProfile;
|
||||
use Illuminate\Support\Arr;
|
||||
use Laravel\Pennant\Middleware\EnsureFeaturesAreActive;
|
||||
|
||||
class SyncExternalProfileResolver extends BaseResolver
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware(EnabledOnlyOnLocalhost::class);
|
||||
$this->middleware(EnsureFeaturesAreActive::using(AllowExternalProfileManagement::class))->only(['update']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function update(array $args): array
|
||||
{
|
||||
$this->runMiddleware();
|
||||
|
||||
/** @var ExternalProfile $profile */
|
||||
$profile = Arr::pull($args, self::MODEL);
|
||||
|
||||
throw_unless(
|
||||
$profile->canBeSynced(),
|
||||
ClientForbiddenException::class,
|
||||
'This external profile cannot be synced at the moment.'
|
||||
);
|
||||
|
||||
$profile->dispatchSyncJob();
|
||||
|
||||
return [
|
||||
'message' => 'Job dispatched.',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Resolvers\User;
|
||||
|
||||
use App\Contracts\Models\Likeable;
|
||||
use App\GraphQL\Resolvers\BaseResolver;
|
||||
use App\GraphQL\Schema\Mutations\Models\User\ToggleLikeMutation;
|
||||
use App\Models\User\Like;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ToggleLikeResolver extends BaseResolver
|
||||
{
|
||||
final public const string ATTRIBUTE_ENTRY = 'entry';
|
||||
final public const string ATTRIBUTE_PLAYLIST = 'playlist';
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function store(array $args): ?Like
|
||||
{
|
||||
$this->runMiddleware();
|
||||
|
||||
$validated = $this->validated($args, ToggleLikeMutation::class);
|
||||
|
||||
/** @var Model&Likeable $likeable */
|
||||
$likeable = Arr::first($validated);
|
||||
|
||||
return $likeable->toggleLike(Auth::user());
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Resolvers\User;
|
||||
|
||||
use App\Actions\Http\Api\StoreAction;
|
||||
use App\GraphQL\Resolvers\BaseResolver;
|
||||
use App\GraphQL\Schema\Mutations\Models\User\WatchMutation;
|
||||
use App\Models\User\WatchHistory;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class WatchResolver extends BaseResolver
|
||||
{
|
||||
final public const string ATTRIBUTE_ENTRY = 'entryId';
|
||||
final public const string ATTRIBUTE_VIDEO = 'videoId';
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
* @param StoreAction<WatchHistory> $action
|
||||
*/
|
||||
public function store(array $args, StoreAction $action): WatchHistory
|
||||
{
|
||||
$this->runMiddleware();
|
||||
|
||||
$validated = $this->validated($args, WatchMutation::class);
|
||||
|
||||
$validated = [
|
||||
WatchHistory::ATTRIBUTE_ENTRY => Arr::integer($validated, 'entryId'),
|
||||
WatchHistory::ATTRIBUTE_VIDEO => Arr::integer($validated, 'videoId'),
|
||||
WatchHistory::ATTRIBUTE_USER => Auth::id(),
|
||||
];
|
||||
|
||||
return $action->store(WatchHistory::query(), $validated);
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Resolvers\Wiki\Anime;
|
||||
|
||||
use App\Actions\GraphQL\IndexAction;
|
||||
use App\GraphQL\Resolvers\BaseResolver;
|
||||
use App\GraphQL\Schema\Fields\Wiki\Anime\AnimeYear\AnimeYearSeason\AnimeYearSeasonSeasonField;
|
||||
use App\GraphQL\Schema\Fields\Wiki\Anime\AnimeYear\AnimeYearSeasonField;
|
||||
use App\GraphQL\Schema\Fields\Wiki\Anime\AnimeYear\AnimeYearSeasonsField;
|
||||
use App\GraphQL\Schema\Fields\Wiki\Anime\AnimeYear\AnimeYearYearField;
|
||||
use App\GraphQL\Schema\Queries\Wiki\AnimeYearsQuery;
|
||||
use App\GraphQL\Schema\Types\Wiki\AnimeType;
|
||||
use App\Models\Wiki\Anime;
|
||||
use App\Rules\GraphQL\Resolver\AnimeYearRule;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Contracts\Pagination\Paginator;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class AnimeYearsResolver extends BaseResolver
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function index(array $args, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
$year = Arr::get($args, AnimeYearsQuery::ARGUMENT_YEAR);
|
||||
|
||||
$fieldSelection = $resolveInfo->getFieldSelection(1);
|
||||
|
||||
Validator::make(['year' => $year], ['year' => new AnimeYearRule($fieldSelection)])
|
||||
->validate();
|
||||
|
||||
return Anime::query()
|
||||
->distinct([Anime::ATTRIBUTE_YEAR, Anime::ATTRIBUTE_SEASON])
|
||||
->orderBy(Anime::ATTRIBUTE_YEAR)
|
||||
->when($year !== null, fn (Builder $query) => $query->whereIn(Anime::ATTRIBUTE_YEAR, $year))
|
||||
->get([Anime::ATTRIBUTE_YEAR, Anime::ATTRIBUTE_SEASON])
|
||||
->groupBy(Anime::ATTRIBUTE_YEAR)
|
||||
->map(fn (Collection $items, int $year): array => [
|
||||
AnimeYearYearField::FIELD => $year,
|
||||
|
||||
AnimeYearSeasonsField::FIELD => $items
|
||||
->map(fn (Anime $anime): array => [
|
||||
AnimeYearSeasonSeasonField::FIELD => $anime->season,
|
||||
'seasonLocalized' => $anime->season->localize(),
|
||||
'year' => $year, // Needed to query animes on the 'seasons' field.
|
||||
])
|
||||
->unique(Anime::ATTRIBUTE_SEASON)
|
||||
->values()
|
||||
->toArray(),
|
||||
])->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the AnimeYearSeasonField.
|
||||
*
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function resolveSeasonField(array $root, array $args): mixed
|
||||
{
|
||||
$season = Arr::get($args, AnimeYearSeasonField::ARGUMENT_SEASON);
|
||||
$year = Arr::get($root, AnimeYearsQuery::ARGUMENT_YEAR);
|
||||
|
||||
$seasons = collect(Arr::get($root, 'seasons'));
|
||||
|
||||
if ($seasons->doesntContain(fn ($item): bool => $item[AnimeYearSeasonSeasonField::FIELD] === $season)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
AnimeYearSeasonSeasonField::FIELD => $season,
|
||||
'seasonLocalized' => $season->localize(),
|
||||
'year' => $year, // Needed to query animes on the 'season' field.
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the AnimeYearSeasonAnimeField.
|
||||
*/
|
||||
public function resolveAnimeField(array $root, array $args, ResolveInfo $resolveInfo, IndexAction $action): Paginator
|
||||
{
|
||||
$season = Arr::get($root, AnimeYearSeasonSeasonField::FIELD);
|
||||
$year = Arr::get($root, 'year');
|
||||
|
||||
$builder = Anime::query()
|
||||
// season filter applies only on the 'season' field.
|
||||
->when($season !== null, fn (Builder $query) => $query->where(Anime::ATTRIBUTE_SEASON, $season->value))
|
||||
->where(Anime::ATTRIBUTE_YEAR, $year);
|
||||
|
||||
return $action->index($builder, $args, new AnimeType(), $resolveInfo);
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,9 @@ use App\Contracts\GraphQL\Fields\FilterableField;
|
||||
use App\Contracts\GraphQL\Fields\RequiredOnCreation;
|
||||
use App\Contracts\GraphQL\Fields\UpdatableField;
|
||||
use App\GraphQL\Filter\IntFilter;
|
||||
use App\GraphQL\Resolvers\List\Playlist\PlaylistTrackResolver;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Mutations\Models\List\Playlist\Track\CreatePlaylistTrackMutation;
|
||||
use App\GraphQL\Schema\Mutations\Models\List\Playlist\Track\UpdatePlaylistTrackMutation;
|
||||
use App\Models\List\Playlist\PlaylistTrack;
|
||||
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
|
||||
use App\Pivots\Wiki\AnimeThemeEntryVideo;
|
||||
@@ -50,7 +51,7 @@ class PlaylistTrackEntryIdField extends Field implements CreatableField, Filtera
|
||||
'integer',
|
||||
Rule::exists(AnimeThemeEntry::class, AnimeThemeEntry::ATTRIBUTE_ID),
|
||||
Rule::exists(AnimeThemeEntryVideo::class, AnimeThemeEntryVideo::ATTRIBUTE_ENTRY)
|
||||
->where(AnimeThemeEntryVideo::ATTRIBUTE_VIDEO, Arr::get($args, PlaylistTrackResolver::ATTRIBUTE_VIDEO)),
|
||||
->where(AnimeThemeEntryVideo::ATTRIBUTE_VIDEO, Arr::get($args, CreatePlaylistTrackMutation::ATTRIBUTE_VIDEO)),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -59,7 +60,7 @@ class PlaylistTrackEntryIdField extends Field implements CreatableField, Filtera
|
||||
*/
|
||||
public function getUpdateRules(array $args): array
|
||||
{
|
||||
$videoId = Arr::get($args, PlaylistTrackResolver::ATTRIBUTE_VIDEO);
|
||||
$videoId = Arr::get($args, UpdatePlaylistTrackMutation::ATTRIBUTE_VIDEO);
|
||||
|
||||
return [
|
||||
'sometimes',
|
||||
|
||||
@@ -9,8 +9,9 @@ use App\Contracts\GraphQL\Fields\FilterableField;
|
||||
use App\Contracts\GraphQL\Fields\RequiredOnCreation;
|
||||
use App\Contracts\GraphQL\Fields\UpdatableField;
|
||||
use App\GraphQL\Filter\IntFilter;
|
||||
use App\GraphQL\Resolvers\List\Playlist\PlaylistTrackResolver;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Mutations\Models\List\Playlist\Track\CreatePlaylistTrackMutation;
|
||||
use App\GraphQL\Schema\Mutations\Models\List\Playlist\Track\UpdatePlaylistTrackMutation;
|
||||
use App\Models\List\Playlist\PlaylistTrack;
|
||||
use App\Models\Wiki\Video;
|
||||
use App\Pivots\Wiki\AnimeThemeEntryVideo;
|
||||
@@ -50,7 +51,7 @@ class PlaylistTrackVideoIdField extends Field implements CreatableField, Filtera
|
||||
'integer',
|
||||
Rule::exists(Video::class, Video::ATTRIBUTE_ID),
|
||||
Rule::exists(AnimeThemeEntryVideo::class, AnimeThemeEntryVideo::ATTRIBUTE_VIDEO)
|
||||
->where(AnimeThemeEntryVideo::ATTRIBUTE_ENTRY, Arr::get($args, PlaylistTrackResolver::ATTRIBUTE_ENTRY)),
|
||||
->where(AnimeThemeEntryVideo::ATTRIBUTE_ENTRY, Arr::get($args, CreatePlaylistTrackMutation::ATTRIBUTE_ENTRY)),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -59,7 +60,7 @@ class PlaylistTrackVideoIdField extends Field implements CreatableField, Filtera
|
||||
*/
|
||||
public function getUpdateRules(array $args): array
|
||||
{
|
||||
$entryId = Arr::get($args, PlaylistTrackResolver::ATTRIBUTE_ENTRY);
|
||||
$entryId = Arr::get($args, UpdatePlaylistTrackMutation::ATTRIBUTE_ENTRY);
|
||||
|
||||
return [
|
||||
'sometimes',
|
||||
|
||||
@@ -6,8 +6,8 @@ namespace App\GraphQL\Schema\Fields\User\Like;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\BindableField;
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\GraphQL\Resolvers\User\ToggleLikeResolver;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Mutations\Models\User\ToggleLikeMutation;
|
||||
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Arr;
|
||||
@@ -36,7 +36,7 @@ class LikeAnimeThemeEntryField extends Field implements BindableField, Creatable
|
||||
public function bindResolver(array $args): AnimeThemeEntry
|
||||
{
|
||||
return AnimeThemeEntry::query()
|
||||
->where(AnimeThemeEntry::ATTRIBUTE_ID, Arr::get($args, ToggleLikeResolver::ATTRIBUTE_ENTRY))
|
||||
->where(AnimeThemeEntry::ATTRIBUTE_ID, Arr::get($args, ToggleLikeMutation::ATTRIBUTE_ENTRY))
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@ class LikeAnimeThemeEntryField extends Field implements BindableField, Creatable
|
||||
public function getCreationRules(array $args): array
|
||||
{
|
||||
return [
|
||||
Str::of('prohibits:')->append(ToggleLikeResolver::ATTRIBUTE_PLAYLIST)->__toString(),
|
||||
Str::of('prohibits:')->append(ToggleLikeMutation::ATTRIBUTE_PLAYLIST)->__toString(),
|
||||
'required_without_all:'.implode(',', [
|
||||
ToggleLikeResolver::ATTRIBUTE_PLAYLIST,
|
||||
ToggleLikeMutation::ATTRIBUTE_PLAYLIST,
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ namespace App\GraphQL\Schema\Fields\User\Like;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\BindableField;
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\GraphQL\Resolvers\User\ToggleLikeResolver;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Mutations\Models\User\ToggleLikeMutation;
|
||||
use App\Models\List\Playlist;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Arr;
|
||||
@@ -36,7 +36,7 @@ class LikePlaylistField extends Field implements BindableField, CreatableField
|
||||
public function bindResolver(array $args): Playlist
|
||||
{
|
||||
return Playlist::query()
|
||||
->where(Playlist::ATTRIBUTE_HASHID, Arr::get($args, ToggleLikeResolver::ATTRIBUTE_PLAYLIST))
|
||||
->where(Playlist::ATTRIBUTE_HASHID, Arr::get($args, ToggleLikeMutation::ATTRIBUTE_PLAYLIST))
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@ class LikePlaylistField extends Field implements BindableField, CreatableField
|
||||
public function getCreationRules(array $args): array
|
||||
{
|
||||
return [
|
||||
Str::of('prohibits:')->append(ToggleLikeResolver::ATTRIBUTE_ENTRY)->__toString(),
|
||||
Str::of('prohibits:')->append(ToggleLikeMutation::ATTRIBUTE_ENTRY)->__toString(),
|
||||
'required_without_all:'.implode(',', [
|
||||
ToggleLikeResolver::ATTRIBUTE_ENTRY,
|
||||
ToggleLikeMutation::ATTRIBUTE_ENTRY,
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ namespace App\GraphQL\Schema\Fields\User\WatchHistory;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\Contracts\GraphQL\Fields\RequiredOnCreation;
|
||||
use App\GraphQL\Resolvers\User\WatchResolver;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Mutations\Models\User\WatchMutation;
|
||||
use App\Models\User\WatchHistory;
|
||||
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
|
||||
use App\Pivots\Wiki\AnimeThemeEntryVideo;
|
||||
@@ -42,7 +42,7 @@ class WatchHistoryEntryIdField extends Field implements CreatableField, Required
|
||||
'integer',
|
||||
Rule::exists(AnimeThemeEntry::class, AnimeThemeEntry::ATTRIBUTE_ID),
|
||||
Rule::exists(AnimeThemeEntryVideo::class, AnimeThemeEntryVideo::ATTRIBUTE_ENTRY)
|
||||
->where(AnimeThemeEntryVideo::ATTRIBUTE_VIDEO, Arr::get($args, WatchResolver::ATTRIBUTE_VIDEO)),
|
||||
->where(AnimeThemeEntryVideo::ATTRIBUTE_VIDEO, Arr::get($args, WatchMutation::ATTRIBUTE_VIDEO)),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ namespace App\GraphQL\Schema\Fields\User\WatchHistory;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\Contracts\GraphQL\Fields\RequiredOnCreation;
|
||||
use App\GraphQL\Resolvers\User\WatchResolver;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Mutations\Models\User\WatchMutation;
|
||||
use App\Models\User\WatchHistory;
|
||||
use App\Models\Wiki\Video;
|
||||
use App\Pivots\Wiki\AnimeThemeEntryVideo;
|
||||
@@ -42,7 +42,7 @@ class WatchHistoryVideoIdField extends Field implements CreatableField, Required
|
||||
'integer',
|
||||
Rule::exists(Video::class, Video::ATTRIBUTE_ID),
|
||||
Rule::exists(AnimeThemeEntryVideo::class, AnimeThemeEntryVideo::ATTRIBUTE_VIDEO)
|
||||
->where(AnimeThemeEntryVideo::ATTRIBUTE_ENTRY, Arr::get($args, WatchResolver::ATTRIBUTE_ENTRY)),
|
||||
->where(AnimeThemeEntryVideo::ATTRIBUTE_ENTRY, Arr::get($args, WatchMutation::ATTRIBUTE_ENTRY)),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
+13
-6
@@ -4,16 +4,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Wiki\Anime\AnimeYear\AnimeYearSeason;
|
||||
|
||||
use App\Actions\GraphQL\IndexAction;
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Argument\Argument;
|
||||
use App\GraphQL\Resolvers\Wiki\Anime\AnimeYearsResolver;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Queries\Models\Pagination\Wiki\AnimePaginationQuery;
|
||||
use App\GraphQL\Schema\Types\Wiki\AnimeType;
|
||||
use App\Models\Wiki\Anime;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Contracts\Pagination\Paginator;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class AnimeYearSeasonAnimeField extends Field implements DisplayableField
|
||||
@@ -77,9 +79,14 @@ class AnimeYearSeasonAnimeField extends Field implements DisplayableField
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return App::call(
|
||||
[App::make(AnimeYearsResolver::class), 'resolveAnimeField'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
);
|
||||
$season = Arr::get($root, AnimeYearSeasonSeasonField::FIELD);
|
||||
$year = Arr::get($root, 'year');
|
||||
|
||||
$builder = Anime::query()
|
||||
// season filter applies only on the 'season' field.
|
||||
->when($season !== null, fn (Builder $query) => $query->where(Anime::ATTRIBUTE_SEASON, $season->value))
|
||||
->where(Anime::ATTRIBUTE_YEAR, $year);
|
||||
|
||||
return new IndexAction()->index($builder, $args, new AnimeType(), $resolveInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@ namespace App\GraphQL\Schema\Fields\Wiki\Anime\AnimeYear;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Enums\Models\Wiki\AnimeSeason;
|
||||
use App\GraphQL\Resolvers\Wiki\Anime\AnimeYearsResolver;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Fields\Wiki\Anime\AnimeYear\AnimeYearSeason\AnimeYearSeasonSeasonField;
|
||||
use App\GraphQL\Schema\Queries\Wiki\AnimeYearsQuery;
|
||||
use App\GraphQL\Schema\Types\Wiki\Anime\AnimeYear\AnimeYearSeasonType;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Arr;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class AnimeYearSeasonField extends Field implements DisplayableField
|
||||
@@ -53,13 +53,23 @@ class AnimeYearSeasonField extends Field implements DisplayableField
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return App::call(
|
||||
[App::make(AnimeYearsResolver::class), 'resolveSeasonField'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
);
|
||||
$season = Arr::get($args, self::ARGUMENT_SEASON);
|
||||
$year = Arr::get($root, AnimeYearsQuery::ARGUMENT_YEAR);
|
||||
|
||||
$seasons = collect(Arr::get($root, 'seasons'));
|
||||
|
||||
if ($seasons->doesntContain(fn ($item): bool => $item[AnimeYearSeasonSeasonField::FIELD] === $season)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
AnimeYearSeasonSeasonField::FIELD => $season,
|
||||
'seasonLocalized' => $season->localize(),
|
||||
'year' => $year, // Needed to query animes on the 'season' field.
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ use App\GraphQL\Middleware\AuthMutation;
|
||||
use App\GraphQL\Middleware\ResolveBindableArgs;
|
||||
use App\GraphQL\Schema\Types\BaseType;
|
||||
use App\GraphQL\Schema\Unions\BaseUnion;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Auth\Access\Response;
|
||||
use Illuminate\Pipeline\Pipeline;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
use Rebing\GraphQL\Support\Mutation;
|
||||
|
||||
@@ -77,8 +77,11 @@ abstract class BaseMutation extends Mutation
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
abstract public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed;
|
||||
protected function runHttpMiddlewares(array $middlewares): void
|
||||
{
|
||||
resolve(Pipeline::class)
|
||||
->send(request())
|
||||
->through($middlewares)
|
||||
->thenReturn();
|
||||
}
|
||||
}
|
||||
|
||||
+25
-5
@@ -5,14 +5,18 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Schema\Mutations\Models\List\ExternalProfile;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\BindableField;
|
||||
use App\Exceptions\GraphQL\ClientForbiddenException;
|
||||
use App\Features\AllowExternalProfileManagement;
|
||||
use App\GraphQL\Argument\Argument;
|
||||
use App\GraphQL\Resolvers\List\SyncExternalProfileResolver;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Mutations\BaseMutation;
|
||||
use App\GraphQL\Schema\Types\List\ExternalProfileType;
|
||||
use App\Http\Middleware\Api\EnabledOnlyOnLocalhost;
|
||||
use App\Models\List\ExternalProfile;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Arr;
|
||||
use Laravel\Pennant\Middleware\EnsureFeaturesAreActive;
|
||||
|
||||
class SyncExternalProfileMutation extends BaseMutation
|
||||
{
|
||||
@@ -59,12 +63,28 @@ class SyncExternalProfileMutation extends BaseMutation
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return App::call(
|
||||
[App::make(SyncExternalProfileResolver::class), 'update'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
$this->runHttpMiddlewares([
|
||||
EnabledOnlyOnLocalhost::class,
|
||||
EnsureFeaturesAreActive::using(AllowExternalProfileManagement::class),
|
||||
]);
|
||||
|
||||
/** @var ExternalProfile $profile */
|
||||
$profile = Arr::pull($args, 'model');
|
||||
|
||||
throw_unless(
|
||||
$profile->canBeSynced(),
|
||||
ClientForbiddenException::class,
|
||||
'This external profile cannot be synced at the moment.'
|
||||
);
|
||||
|
||||
$profile->dispatchSyncJob();
|
||||
|
||||
return [
|
||||
'message' => 'Job dispatched.',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,16 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Mutations\Models\List\Playlist;
|
||||
|
||||
use App\GraphQL\Resolvers\List\PlaylistResolver;
|
||||
use App\Actions\Http\Api\StoreAction;
|
||||
use App\Features\AllowPlaylistManagement;
|
||||
use App\GraphQL\Schema\Mutations\Models\CreateMutation;
|
||||
use App\GraphQL\Schema\Types\List\PlaylistType;
|
||||
use App\Http\Middleware\Models\List\UserExceedsPlaylistLimit;
|
||||
use App\Models\List\Playlist;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Pennant\Middleware\EnsureFeaturesAreActive;
|
||||
|
||||
class CreatePlaylistMutation extends CreateMutation
|
||||
{
|
||||
@@ -28,12 +32,22 @@ class CreatePlaylistMutation extends CreateMutation
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
* @param StoreAction<Playlist> $action
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, StoreAction $action): Playlist
|
||||
{
|
||||
return App::call(
|
||||
[App::make(PlaylistResolver::class), 'store'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
);
|
||||
$this->runHttpMiddlewares([
|
||||
EnsureFeaturesAreActive::using(AllowPlaylistManagement::class),
|
||||
UserExceedsPlaylistLimit::class,
|
||||
]);
|
||||
|
||||
$validated = Validator::make($args, $this->rulesForValidation($args))->validated();
|
||||
|
||||
$parameters = [
|
||||
...$validated,
|
||||
Playlist::ATTRIBUTE_USER => Auth::id(),
|
||||
];
|
||||
|
||||
return $action->store(Playlist::query(), $parameters);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,16 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Mutations\Models\List\Playlist;
|
||||
|
||||
use App\GraphQL\Resolvers\List\PlaylistResolver;
|
||||
use App\Actions\Http\Api\DestroyAction;
|
||||
use App\Features\AllowPlaylistManagement;
|
||||
use App\GraphQL\Schema\Mutations\Models\DeleteMutation;
|
||||
use App\GraphQL\Schema\Types\List\PlaylistType;
|
||||
use App\GraphQL\Schema\Types\MessageResponseType;
|
||||
use App\Models\List\Playlist;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Arr;
|
||||
use Laravel\Pennant\Middleware\EnsureFeaturesAreActive;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class DeletePlaylistMutation extends DeleteMutation
|
||||
@@ -36,12 +38,22 @@ class DeletePlaylistMutation extends DeleteMutation
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
* @param DestroyAction<Playlist> $action
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, DestroyAction $action): array
|
||||
{
|
||||
return App::call(
|
||||
[App::make(PlaylistResolver::class), 'destroy'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
);
|
||||
$this->runHttpMiddlewares([
|
||||
EnsureFeaturesAreActive::using(AllowPlaylistManagement::class),
|
||||
]);
|
||||
|
||||
/** @var Playlist $playlist */
|
||||
$playlist = Arr::pull($args, 'model');
|
||||
|
||||
$message = $action->forceDelete($playlist);
|
||||
|
||||
return [
|
||||
'message' => $message,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
+27
-7
@@ -4,16 +4,25 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Mutations\Models\List\Playlist\Track;
|
||||
|
||||
use App\GraphQL\Resolvers\List\Playlist\PlaylistTrackResolver;
|
||||
use App\Actions\Http\Api\List\Playlist\Track\StoreTrackAction;
|
||||
use App\Features\AllowPlaylistManagement;
|
||||
use App\GraphQL\Schema\Mutations\Models\CreateMutation;
|
||||
use App\GraphQL\Schema\Types\List\Playlist\PlaylistTrackType;
|
||||
use App\Http\Middleware\Models\List\PlaylistExceedsTrackLimit;
|
||||
use App\Models\List\Playlist;
|
||||
use App\Models\List\Playlist\PlaylistTrack;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Pennant\Middleware\EnsureFeaturesAreActive;
|
||||
|
||||
class CreatePlaylistTrackMutation extends CreateMutation
|
||||
{
|
||||
public static Playlist $playlist;
|
||||
|
||||
final public const string ATTRIBUTE_ENTRY = 'entryId';
|
||||
final public const string ATTRIBUTE_VIDEO = 'videoId';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(PlaylistTrack::class);
|
||||
@@ -30,11 +39,22 @@ class CreatePlaylistTrackMutation extends CreateMutation
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, StoreTrackAction $action): PlaylistTrack
|
||||
{
|
||||
return App::call(
|
||||
[App::make(PlaylistTrackResolver::class, ['playlist' => Arr::get($args, 'playlist')]), 'store'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
);
|
||||
static::$playlist = Arr::get($args, 'playlist');
|
||||
|
||||
$this->runHttpMiddlewares([
|
||||
EnsureFeaturesAreActive::using(AllowPlaylistManagement::class),
|
||||
PlaylistExceedsTrackLimit::class,
|
||||
]);
|
||||
|
||||
$validated = Validator::make($args, $this->rulesForValidation($args))->validated();
|
||||
|
||||
$validated = [
|
||||
PlaylistTrack::ATTRIBUTE_ENTRY => Arr::integer($validated, 'entryId'),
|
||||
PlaylistTrack::ATTRIBUTE_VIDEO => Arr::integer($validated, 'videoId'),
|
||||
];
|
||||
|
||||
return $action->store(static::$playlist, PlaylistTrack::query(), $validated);
|
||||
}
|
||||
}
|
||||
|
||||
+17
-7
@@ -4,7 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Mutations\Models\List\Playlist\Track;
|
||||
|
||||
use App\GraphQL\Resolvers\List\Playlist\PlaylistTrackResolver;
|
||||
use App\Actions\Http\Api\List\Playlist\Track\DestroyTrackAction;
|
||||
use App\Features\AllowPlaylistManagement;
|
||||
use App\GraphQL\Schema\Mutations\Models\DeleteMutation;
|
||||
use App\GraphQL\Schema\Types\List\Playlist\PlaylistTrackType;
|
||||
use App\GraphQL\Schema\Types\MessageResponseType;
|
||||
@@ -12,7 +13,7 @@ use App\Models\List\Playlist\PlaylistTrack;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Laravel\Pennant\Middleware\EnsureFeaturesAreActive;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class DeletePlaylistTrackMutation extends DeleteMutation
|
||||
@@ -37,12 +38,21 @@ class DeletePlaylistTrackMutation extends DeleteMutation
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, DestroyTrackAction $action): array
|
||||
{
|
||||
return App::call(
|
||||
[App::make(PlaylistTrackResolver::class, ['playlist' => Arr::get($args, 'playlist')]), 'destroy'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
);
|
||||
$this->runHttpMiddlewares([
|
||||
EnsureFeaturesAreActive::using(AllowPlaylistManagement::class),
|
||||
]);
|
||||
|
||||
/** @var PlaylistTrack $track */
|
||||
$track = Arr::pull($args, 'model');
|
||||
|
||||
$message = $action->destroy($track->playlist, $track);
|
||||
|
||||
return [
|
||||
'message' => $message,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
+23
-7
@@ -4,16 +4,21 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Mutations\Models\List\Playlist\Track;
|
||||
|
||||
use App\GraphQL\Resolvers\List\Playlist\PlaylistTrackResolver;
|
||||
use App\Actions\Http\Api\List\Playlist\Track\UpdateTrackAction;
|
||||
use App\Features\AllowPlaylistManagement;
|
||||
use App\GraphQL\Schema\Mutations\Models\UpdateMutation;
|
||||
use App\GraphQL\Schema\Types\List\Playlist\PlaylistTrackType;
|
||||
use App\Models\List\Playlist\PlaylistTrack;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Pennant\Middleware\EnsureFeaturesAreActive;
|
||||
|
||||
class UpdatePlaylistTrackMutation extends UpdateMutation
|
||||
{
|
||||
final public const string ATTRIBUTE_ENTRY = 'entryId';
|
||||
final public const string ATTRIBUTE_VIDEO = 'videoId';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(PlaylistTrack::class);
|
||||
@@ -30,11 +35,22 @@ class UpdatePlaylistTrackMutation extends UpdateMutation
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, UpdateTrackAction $action): PlaylistTrack
|
||||
{
|
||||
return App::call(
|
||||
[App::make(PlaylistTrackResolver::class, ['playlist' => Arr::get($args, 'playlist')]), 'update'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
);
|
||||
$this->runHttpMiddlewares([
|
||||
EnsureFeaturesAreActive::using(AllowPlaylistManagement::class),
|
||||
]);
|
||||
|
||||
/** @var PlaylistTrack $track */
|
||||
$track = Arr::get($args, 'model');
|
||||
|
||||
$validated = Validator::make($args, $this->rulesForValidation($args))->validated();
|
||||
|
||||
$validated = [
|
||||
PlaylistTrack::ATTRIBUTE_ENTRY => Arr::integer($validated, 'entryId'),
|
||||
PlaylistTrack::ATTRIBUTE_VIDEO => Arr::integer($validated, 'videoId'),
|
||||
];
|
||||
|
||||
return $action->update($track->playlist, $track, $validated);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Mutations\Models\List\Playlist;
|
||||
|
||||
use App\GraphQL\Resolvers\List\PlaylistResolver;
|
||||
use App\Actions\Http\Api\UpdateAction;
|
||||
use App\Features\AllowPlaylistManagement;
|
||||
use App\GraphQL\Schema\Mutations\Models\UpdateMutation;
|
||||
use App\GraphQL\Schema\Types\List\PlaylistType;
|
||||
use App\Models\List\Playlist;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Pennant\Middleware\EnsureFeaturesAreActive;
|
||||
|
||||
class UpdatePlaylistMutation extends UpdateMutation
|
||||
{
|
||||
@@ -28,12 +31,19 @@ class UpdatePlaylistMutation extends UpdateMutation
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
* @param UpdateAction<Playlist> $action
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, UpdateAction $action): Playlist
|
||||
{
|
||||
return App::call(
|
||||
[App::make(PlaylistResolver::class), 'update'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
);
|
||||
$this->runHttpMiddlewares([
|
||||
EnsureFeaturesAreActive::using(AllowPlaylistManagement::class),
|
||||
]);
|
||||
|
||||
/** @var Playlist $playlist */
|
||||
$playlist = Arr::pull($args, 'model');
|
||||
|
||||
$validated = Validator::make($args, $this->rulesForValidation($args))->validated();
|
||||
|
||||
return $action->update($playlist, $validated);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,20 +5,26 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Schema\Mutations\Models\User;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\Contracts\Models\Likeable;
|
||||
use App\GraphQL\Argument\Argument;
|
||||
use App\GraphQL\Resolvers\User\ToggleLikeResolver;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Mutations\BaseMutation;
|
||||
use App\GraphQL\Schema\Types\User\LikeType;
|
||||
use App\Models\User\Like;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class ToggleLikeMutation extends BaseMutation
|
||||
{
|
||||
final public const string ATTRIBUTE_ENTRY = 'entry';
|
||||
final public const string ATTRIBUTE_PLAYLIST = 'playlist';
|
||||
|
||||
public function name(): string
|
||||
{
|
||||
return 'ToggleLike';
|
||||
@@ -70,12 +76,15 @@ class ToggleLikeMutation extends BaseMutation
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
* @return Like|null
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return App::call(
|
||||
[App::make(ToggleLikeResolver::class), 'store'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
);
|
||||
$validated = Validator::make($args, $this->rulesForValidation($args))->validated();
|
||||
|
||||
/** @var Model&Likeable $likeable */
|
||||
$likeable = Arr::first($validated);
|
||||
|
||||
return $likeable->toggleLike(Auth::user());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,22 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Mutations\Models\User;
|
||||
|
||||
use App\GraphQL\Resolvers\User\WatchResolver;
|
||||
use App\Actions\Http\Api\StoreAction;
|
||||
use App\GraphQL\Schema\Mutations\Models\CreateMutation;
|
||||
use App\GraphQL\Schema\Types\User\WatchHistoryType;
|
||||
use App\Models\User\WatchHistory;
|
||||
use Closure;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class WatchMutation extends CreateMutation
|
||||
{
|
||||
final public const string ATTRIBUTE_ENTRY = 'entryId';
|
||||
final public const string ATTRIBUTE_VIDEO = 'videoId';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(WatchHistory::class);
|
||||
@@ -45,12 +50,18 @@ class WatchMutation extends CreateMutation
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
* @param StoreAction<WatchHistory> $action
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, StoreAction $action): WatchHistory
|
||||
{
|
||||
return App::call(
|
||||
[App::make(WatchResolver::class), 'store'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
);
|
||||
$validated = Validator::make($args, $this->rulesForValidation($args))->validated();
|
||||
|
||||
$validated = [
|
||||
WatchHistory::ATTRIBUTE_ENTRY => Arr::integer($validated, 'entryId'),
|
||||
WatchHistory::ATTRIBUTE_VIDEO => Arr::integer($validated, 'videoId'),
|
||||
WatchHistory::ATTRIBUTE_USER => Auth::id(),
|
||||
];
|
||||
|
||||
return $action->store(WatchHistory::query(), $validated);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ use App\GraphQL\Schema\Queries\BaseQuery;
|
||||
use App\GraphQL\Schema\Types\Admin\FeaturedThemeType;
|
||||
use App\Models\Admin\FeaturedTheme;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
|
||||
class CurrentFeaturedThemeQuery extends BaseQuery
|
||||
@@ -43,12 +42,9 @@ class CurrentFeaturedThemeQuery extends BaseQuery
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the query.
|
||||
*
|
||||
* @param array<string, mixed> $args
|
||||
* @return FeaturedTheme|null
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): ?Model
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): ?FeaturedTheme
|
||||
{
|
||||
$builder = FeaturedTheme::query();
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ use App\GraphQL\Argument\Argument;
|
||||
use App\GraphQL\Schema\Queries\BaseQuery;
|
||||
use App\GraphQL\Schema\Types\Auth\User\MeType;
|
||||
use App\Models\Auth\User;
|
||||
use Closure;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
@@ -42,12 +41,7 @@ class MeQuery extends BaseQuery
|
||||
return new MeType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the query.
|
||||
*
|
||||
* @return User|null
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, Closure $getSelectFields)
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): ?User
|
||||
{
|
||||
$builder = User::query()->whereKey(Auth::id());
|
||||
|
||||
|
||||
@@ -50,12 +50,7 @@ abstract class EloquentPaginationQuery extends EloquentQuery
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the pagination query.
|
||||
*
|
||||
* @return Paginator
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, IndexAction $action)
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, IndexAction $action): Paginator
|
||||
{
|
||||
$builder = $this->model()::query();
|
||||
|
||||
|
||||
@@ -54,10 +54,8 @@ abstract class EloquentSingularQuery extends EloquentQuery
|
||||
|
||||
/**
|
||||
* Resolve the singular record with the binded argument.
|
||||
*
|
||||
* @return Model
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, ShowAction $action)
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, ShowAction $action): Model
|
||||
{
|
||||
/** @var Model $model */
|
||||
$model = Arr::get($args, 'model');
|
||||
|
||||
@@ -5,18 +5,22 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Schema\Queries\Wiki;
|
||||
|
||||
use App\GraphQL\Argument\Argument;
|
||||
use App\GraphQL\Resolvers\Wiki\Anime\AnimeYearsResolver;
|
||||
use App\GraphQL\Schema\Fields\Wiki\Anime\AnimeYear\AnimeYearSeason\AnimeYearSeasonSeasonField;
|
||||
use App\GraphQL\Schema\Fields\Wiki\Anime\AnimeYear\AnimeYearSeasonsField;
|
||||
use App\GraphQL\Schema\Fields\Wiki\Anime\AnimeYear\AnimeYearYearField;
|
||||
use App\GraphQL\Schema\Queries\BaseQuery;
|
||||
use App\GraphQL\Schema\Types\Wiki\Anime\AnimeYearType;
|
||||
use App\Models\Wiki\Anime;
|
||||
use App\Rules\GraphQL\Resolver\AnimeYearRule;
|
||||
use Closure;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class AnimeYearsQuery extends BaseQuery
|
||||
{
|
||||
@@ -69,14 +73,33 @@ class AnimeYearsQuery extends BaseQuery
|
||||
return new AnimeYearType();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo)
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): Collection
|
||||
{
|
||||
return App::call(
|
||||
[App::make(AnimeYearsResolver::class), 'index'],
|
||||
['root' => $root, 'args' => $args, 'context' => $context, 'resolveInfo' => $resolveInfo]
|
||||
);
|
||||
$year = Arr::get($args, self::ARGUMENT_YEAR);
|
||||
|
||||
$fieldSelection = $resolveInfo->getFieldSelection(1);
|
||||
|
||||
Validator::make(['year' => $year], ['year' => new AnimeYearRule($fieldSelection)])
|
||||
->validate();
|
||||
|
||||
return Anime::query()
|
||||
->distinct([Anime::ATTRIBUTE_YEAR, Anime::ATTRIBUTE_SEASON])
|
||||
->orderBy(Anime::ATTRIBUTE_YEAR)
|
||||
->when($year !== null, fn (Builder $query) => $query->whereIn(Anime::ATTRIBUTE_YEAR, $year))
|
||||
->get([Anime::ATTRIBUTE_YEAR, Anime::ATTRIBUTE_SEASON])
|
||||
->groupBy(Anime::ATTRIBUTE_YEAR)
|
||||
->map(fn (Collection $items, int $year): array => [
|
||||
AnimeYearYearField::FIELD => $year,
|
||||
|
||||
AnimeYearSeasonsField::FIELD => $items
|
||||
->map(fn (Anime $anime): array => [
|
||||
AnimeYearSeasonSeasonField::FIELD => $anime->season,
|
||||
'seasonLocalized' => $anime->season->localize(),
|
||||
'year' => $year, // Needed to query animes on the 'seasons' field.
|
||||
])
|
||||
->unique(Anime::ATTRIBUTE_SEASON)
|
||||
->values()
|
||||
->toArray(),
|
||||
])->values();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,10 +72,7 @@ class FindAnimeByExternalSiteQuery extends BaseQuery
|
||||
return new AnimeType();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo)
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): Collection
|
||||
{
|
||||
Validator::make($args, [
|
||||
self::ATTRIBUTE_SITE => ['required', new Enum(ResourceSite::class)],
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace App\Http\Middleware\Models\List;
|
||||
|
||||
use App\Constants\Config\PlaylistConstants;
|
||||
use App\Enums\Auth\SpecialPermission;
|
||||
use App\GraphQL\Resolvers\List\Playlist\PlaylistTrackResolver;
|
||||
use App\GraphQL\Schema\Mutations\Models\List\Playlist\Track\CreatePlaylistTrackMutation;
|
||||
use App\Models\Auth\User;
|
||||
use App\Models\List\Playlist;
|
||||
use Closure;
|
||||
@@ -23,7 +23,7 @@ class PlaylistExceedsTrackLimit
|
||||
$trackLimit = intval(Config::get(PlaylistConstants::MAX_TRACKS_QUALIFIED));
|
||||
|
||||
/** @var Playlist|null $playlist */
|
||||
$playlist = $request->route('playlist') ?? PlaylistTrackResolver::$playlist;
|
||||
$playlist = $request->route('playlist') ?? CreatePlaylistTrackMutation::$playlist;
|
||||
|
||||
/** @var User|null $user */
|
||||
$user = $request->user();
|
||||
|
||||
Reference in New Issue
Block a user