mirror of
https://github.com/jikan-me/jikan-rest.git
synced 2025-02-20 11:23:35 +08:00
refactored user endpoints and cache ttl config
This commit is contained in:
parent
525ac030f3
commit
4a25c30d7d
@ -12,8 +12,8 @@ use Jikan\Model\Common\DateProp;
|
|||||||
*/
|
*/
|
||||||
class CarbonDateRange
|
class CarbonDateRange
|
||||||
{
|
{
|
||||||
private ?Carbon $fromObj;
|
private ?Carbon $fromObj = null;
|
||||||
private ?Carbon $untilObj;
|
private ?Carbon $untilObj = null;
|
||||||
|
|
||||||
public function __construct(?Carbon $from, ?Carbon $to)
|
public function __construct(?Carbon $from, ?Carbon $to)
|
||||||
{
|
{
|
||||||
|
@ -13,7 +13,7 @@ use Spatie\LaravelData\Resolvers\DataFromSomethingResolver;
|
|||||||
*/
|
*/
|
||||||
trait HasRequestFingerprint
|
trait HasRequestFingerprint
|
||||||
{
|
{
|
||||||
protected ?string $fingerprint;
|
protected ?string $fingerprint = null;
|
||||||
|
|
||||||
public static function fromRequest(Request $request): ?static
|
public static function fromRequest(Request $request): ?static
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@ use App\Enums\AnimeScheduleFilterEnum;
|
|||||||
use App\Enums\AnimeTypeEnum;
|
use App\Enums\AnimeTypeEnum;
|
||||||
use Illuminate\Contracts\Database\Query\Builder as EloquentBuilder;
|
use Illuminate\Contracts\Database\Query\Builder as EloquentBuilder;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use \Laravel\Scout\Builder as ScoutBuilder;
|
use Laravel\Scout\Builder as ScoutBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements Repository<Anime>
|
* @implements Repository<Anime>
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
namespace App\Contracts;
|
namespace App\Contracts;
|
||||||
|
|
||||||
use App\Character;
|
use App\Character;
|
||||||
use \Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
use Illuminate\Contracts\Database\Query\Builder as EloquentBuilder;
|
||||||
use \Laravel\Scout\Builder as ScoutBuilder;
|
use Laravel\Scout\Builder as ScoutBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements Repository<Character>
|
* @implements Repository<Character>
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
namespace App\Contracts;
|
namespace App\Contracts;
|
||||||
|
|
||||||
use App\Person;
|
use App\Person;
|
||||||
use \Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
use Illuminate\Contracts\Database\Query\Builder as EloquentBuilder;
|
||||||
use \Laravel\Scout\Builder as ScoutBuilder;
|
use Laravel\Scout\Builder as ScoutBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements Repository<Person>
|
* @implements Repository<Person>
|
||||||
|
@ -5,9 +5,9 @@ namespace App\Dto;
|
|||||||
use App\Casts\EnumCast;
|
use App\Casts\EnumCast;
|
||||||
use App\Enums\AnimeForumFilterEnum;
|
use App\Enums\AnimeForumFilterEnum;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends LookupDataCommand<JsonResponse>
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace App\Dto;
|
namespace App\Dto;
|
||||||
|
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\Min;
|
use Spatie\LaravelData\Attributes\Validation\Min;
|
||||||
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends LookupDataCommand<JsonResponse>
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
@ -6,11 +6,11 @@ use App\Casts\EnumCast;
|
|||||||
use App\Contracts\DataRequest;
|
use App\Contracts\DataRequest;
|
||||||
use App\Enums\CharacterOrderByEnum;
|
use App\Enums\CharacterOrderByEnum;
|
||||||
use App\Http\Resources\V4\CharacterCollection;
|
use App\Http\Resources\V4\CharacterCollection;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\MapInputName;
|
use Spatie\LaravelData\Attributes\MapInputName;
|
||||||
use Spatie\LaravelData\Attributes\MapOutputName;
|
use Spatie\LaravelData\Attributes\MapOutputName;
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements DataRequest<CharacterCollection>
|
* @implements DataRequest<CharacterCollection>
|
||||||
|
@ -8,11 +8,11 @@ use App\Enums\ClubCategoryEnum;
|
|||||||
use App\Enums\ClubOrderByEnum;
|
use App\Enums\ClubOrderByEnum;
|
||||||
use App\Enums\ClubTypeEnum;
|
use App\Enums\ClubTypeEnum;
|
||||||
use App\Http\Resources\V4\ClubCollection;
|
use App\Http\Resources\V4\ClubCollection;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\MapInputName;
|
use Spatie\LaravelData\Attributes\MapInputName;
|
||||||
use Spatie\LaravelData\Attributes\MapOutputName;
|
use Spatie\LaravelData\Attributes\MapOutputName;
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements DataRequest<ClubCollection>
|
* @implements DataRequest<ClubCollection>
|
||||||
|
16
app/Dto/Concerns/HasLimitParameter.php
Normal file
16
app/Dto/Concerns/HasLimitParameter.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto\Concerns;
|
||||||
|
|
||||||
|
use App\Rules\Attributes\MaxLimitWithFallback;
|
||||||
|
use Spatie\LaravelData\Attributes\Validation\IntegerType;
|
||||||
|
use Spatie\LaravelData\Attributes\Validation\Min;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
|
trait HasLimitParameter
|
||||||
|
{
|
||||||
|
use MapsDefaultLimitParameter;
|
||||||
|
|
||||||
|
#[IntegerType, Min(1), MaxLimitWithFallback]
|
||||||
|
public int|Optional $limit;
|
||||||
|
}
|
13
app/Dto/Concerns/HasPageParameter.php
Normal file
13
app/Dto/Concerns/HasPageParameter.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto\Concerns;
|
||||||
|
|
||||||
|
use Spatie\LaravelData\Attributes\Validation\Min;
|
||||||
|
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
|
trait HasPageParameter
|
||||||
|
{
|
||||||
|
#[Numeric, Min(1)]
|
||||||
|
public int|Optional $page = 1;
|
||||||
|
}
|
27
app/Dto/LookupByUsernameCommand.php
Normal file
27
app/Dto/LookupByUsernameCommand.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
use App\Concerns\HasRequestFingerprint;
|
||||||
|
use App\Contracts\DataRequest;
|
||||||
|
use App\Dto\Concerns\MapsRouteParameters;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Spatie\LaravelData\Attributes\Validation\Max;
|
||||||
|
use Spatie\LaravelData\Attributes\Validation\Min;
|
||||||
|
use Spatie\LaravelData\Attributes\Validation\StringType;
|
||||||
|
use Spatie\LaravelData\Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all requests/commands which are for looking up things by username.
|
||||||
|
* @template T of ResourceCollection|JsonResource|Response
|
||||||
|
* @implements DataRequest<T>
|
||||||
|
*/
|
||||||
|
abstract class LookupByUsernameCommand extends Data implements DataRequest
|
||||||
|
{
|
||||||
|
use MapsRouteParameters, HasRequestFingerprint;
|
||||||
|
|
||||||
|
#[StringType, Max(255), Min(3)]
|
||||||
|
public string $username;
|
||||||
|
}
|
@ -6,11 +6,11 @@ use App\Casts\EnumCast;
|
|||||||
use App\Contracts\DataRequest;
|
use App\Contracts\DataRequest;
|
||||||
use App\Enums\MagazineOrderByEnum;
|
use App\Enums\MagazineOrderByEnum;
|
||||||
use App\Http\Resources\V4\MagazineCollection;
|
use App\Http\Resources\V4\MagazineCollection;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\MapInputName;
|
use Spatie\LaravelData\Attributes\MapInputName;
|
||||||
use Spatie\LaravelData\Attributes\MapOutputName;
|
use Spatie\LaravelData\Attributes\MapOutputName;
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements DataRequest<MagazineCollection>
|
* @implements DataRequest<MagazineCollection>
|
||||||
|
@ -6,9 +6,9 @@ namespace App\Dto;
|
|||||||
use App\Casts\EnumCast;
|
use App\Casts\EnumCast;
|
||||||
use App\Enums\MangaForumFilterEnum;
|
use App\Enums\MangaForumFilterEnum;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends LookupDataCommand<JsonResponse>
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
@ -6,11 +6,11 @@ use App\Casts\EnumCast;
|
|||||||
use App\Contracts\DataRequest;
|
use App\Contracts\DataRequest;
|
||||||
use App\Enums\PeopleOrderByEnum;
|
use App\Enums\PeopleOrderByEnum;
|
||||||
use App\Http\Resources\V4\PersonCollection;
|
use App\Http\Resources\V4\PersonCollection;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\MapInputName;
|
use Spatie\LaravelData\Attributes\MapInputName;
|
||||||
use Spatie\LaravelData\Attributes\MapOutputName;
|
use Spatie\LaravelData\Attributes\MapOutputName;
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements DataRequest<PersonCollection>
|
* @implements DataRequest<PersonCollection>
|
||||||
|
@ -6,11 +6,11 @@ use App\Casts\EnumCast;
|
|||||||
use App\Contracts\DataRequest;
|
use App\Contracts\DataRequest;
|
||||||
use App\Enums\ProducerOrderByEnum;
|
use App\Enums\ProducerOrderByEnum;
|
||||||
use App\Http\Resources\V4\ProducerCollection;
|
use App\Http\Resources\V4\ProducerCollection;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\MapInputName;
|
use Spatie\LaravelData\Attributes\MapInputName;
|
||||||
use Spatie\LaravelData\Attributes\MapOutputName;
|
use Spatie\LaravelData\Attributes\MapOutputName;
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements DataRequest<ProducerCollection>
|
* @implements DataRequest<ProducerCollection>
|
||||||
|
@ -6,18 +6,14 @@ namespace App\Dto;
|
|||||||
use App\Casts\EnumCast;
|
use App\Casts\EnumCast;
|
||||||
use App\Concerns\HasRequestFingerprint;
|
use App\Concerns\HasRequestFingerprint;
|
||||||
use App\Contracts\DataRequest;
|
use App\Contracts\DataRequest;
|
||||||
use App\Dto\Concerns\MapsDefaultLimitParameter;
|
use App\Dto\Concerns\HasLimitParameter;
|
||||||
|
use App\Dto\Concerns\HasPageParameter;
|
||||||
use App\Enums\AnimeScheduleFilterEnum;
|
use App\Enums\AnimeScheduleFilterEnum;
|
||||||
use App\Rules\Attributes\MaxLimitWithFallback;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Env;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\Validation\BooleanType;
|
use Spatie\LaravelData\Attributes\Validation\BooleanType;
|
||||||
use Spatie\LaravelData\Attributes\Validation\IntegerType;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\Min;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\Nullable;
|
use Spatie\LaravelData\Attributes\Validation\Nullable;
|
||||||
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
use Spatie\LaravelData\Data;
|
use Spatie\LaravelData\Data;
|
||||||
use Spatie\LaravelData\Optional;
|
use Spatie\LaravelData\Optional;
|
||||||
@ -27,13 +23,7 @@ use Spatie\LaravelData\Optional;
|
|||||||
*/
|
*/
|
||||||
final class QueryAnimeSchedulesCommand extends Data implements DataRequest
|
final class QueryAnimeSchedulesCommand extends Data implements DataRequest
|
||||||
{
|
{
|
||||||
use MapsDefaultLimitParameter, HasRequestFingerprint;
|
use HasLimitParameter, HasRequestFingerprint, HasPageParameter;
|
||||||
|
|
||||||
#[Numeric, Min(1)]
|
|
||||||
public int|Optional $page = 1;
|
|
||||||
|
|
||||||
#[IntegerType, Min(1), MaxLimitWithFallback]
|
|
||||||
public int|Optional $limit;
|
|
||||||
|
|
||||||
#[BooleanType]
|
#[BooleanType]
|
||||||
public bool|Optional $kids = false;
|
public bool|Optional $kids = false;
|
||||||
|
@ -6,12 +6,10 @@ namespace App\Dto;
|
|||||||
use App\Casts\EnumCast;
|
use App\Casts\EnumCast;
|
||||||
use App\Concerns\HasRequestFingerprint;
|
use App\Concerns\HasRequestFingerprint;
|
||||||
use App\Contracts\DataRequest;
|
use App\Contracts\DataRequest;
|
||||||
use App\Dto\Concerns\MapsDefaultLimitParameter;
|
use App\Dto\Concerns\HasLimitParameter;
|
||||||
|
use App\Dto\Concerns\HasPageParameter;
|
||||||
use App\Enums\AnimeTypeEnum;
|
use App\Enums\AnimeTypeEnum;
|
||||||
use App\Rules\Attributes\MaxLimitWithFallback;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\Validation\Min;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
use Spatie\LaravelData\Data;
|
use Spatie\LaravelData\Data;
|
||||||
use Spatie\LaravelData\Optional;
|
use Spatie\LaravelData\Optional;
|
||||||
@ -19,18 +17,11 @@ use Spatie\LaravelData\Optional;
|
|||||||
|
|
||||||
abstract class QueryAnimeSeasonCommand extends Data implements DataRequest
|
abstract class QueryAnimeSeasonCommand extends Data implements DataRequest
|
||||||
{
|
{
|
||||||
use MapsDefaultLimitParameter, HasRequestFingerprint;
|
use HasLimitParameter, HasRequestFingerprint, HasPageParameter;
|
||||||
|
|
||||||
#[WithCast(EnumCast::class, AnimeTypeEnum::class)]
|
#[WithCast(EnumCast::class, AnimeTypeEnum::class)]
|
||||||
public AnimeTypeEnum|Optional $filter;
|
public AnimeTypeEnum|Optional $filter;
|
||||||
|
|
||||||
#[Numeric, Min(1)]
|
|
||||||
public int|Optional $page = 1;
|
|
||||||
|
|
||||||
#[Numeric, Min(1), MaxLimitWithFallback]
|
|
||||||
public int|Optional $limit;
|
|
||||||
|
|
||||||
|
|
||||||
public static function rules(...$args): array
|
public static function rules(...$args): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
@ -4,9 +4,9 @@ namespace App\Dto;
|
|||||||
|
|
||||||
use App\Contracts\DataRequest;
|
use App\Contracts\DataRequest;
|
||||||
use App\Http\Resources\V4\AnimeResource;
|
use App\Http\Resources\V4\AnimeResource;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\BooleanType;
|
use Spatie\LaravelData\Attributes\Validation\BooleanType;
|
||||||
use Spatie\LaravelData\Data;
|
use Spatie\LaravelData\Data;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements DataRequest<AnimeResource>
|
* @implements DataRequest<AnimeResource>
|
||||||
|
@ -4,9 +4,9 @@ namespace App\Dto;
|
|||||||
|
|
||||||
use App\Contracts\DataRequest;
|
use App\Contracts\DataRequest;
|
||||||
use App\Http\Resources\V4\MangaResource;
|
use App\Http\Resources\V4\MangaResource;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\BooleanType;
|
use Spatie\LaravelData\Attributes\Validation\BooleanType;
|
||||||
use Spatie\LaravelData\Data;
|
use Spatie\LaravelData\Data;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements DataRequest<MangaResource>
|
* @implements DataRequest<MangaResource>
|
||||||
|
15
app/Dto/QueryRecentlyOnlineUsersCommand.php
Normal file
15
app/Dto/QueryRecentlyOnlineUsersCommand.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Contracts\DataRequest;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Spatie\LaravelData\Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends DataRequest<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class QueryRecentlyOnlineUsersCommand extends Data implements DataRequest
|
||||||
|
{
|
||||||
|
}
|
@ -6,6 +6,7 @@ namespace App\Dto;
|
|||||||
use App\Casts\EnumCast;
|
use App\Casts\EnumCast;
|
||||||
use App\Concerns\HasRequestFingerprint;
|
use App\Concerns\HasRequestFingerprint;
|
||||||
use App\Contracts\DataRequest;
|
use App\Contracts\DataRequest;
|
||||||
|
use App\Dto\Concerns\HasPageParameter;
|
||||||
use App\Enums\MediaReviewsSortEnum;
|
use App\Enums\MediaReviewsSortEnum;
|
||||||
use App\Http\Resources\V4\ResultsResource;
|
use App\Http\Resources\V4\ResultsResource;
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
@ -21,10 +22,7 @@ use Spatie\LaravelData\Optional;
|
|||||||
*/
|
*/
|
||||||
abstract class QueryReviewsCommand extends Data implements DataRequest
|
abstract class QueryReviewsCommand extends Data implements DataRequest
|
||||||
{
|
{
|
||||||
use HasRequestFingerprint;
|
use HasRequestFingerprint, HasPageParameter;
|
||||||
|
|
||||||
#[Numeric, Min(1)]
|
|
||||||
public int|Optional $page = 1;
|
|
||||||
|
|
||||||
#[WithCast(EnumCast::class, MediaReviewsSortEnum::class)]
|
#[WithCast(EnumCast::class, MediaReviewsSortEnum::class)]
|
||||||
public MediaReviewsSortEnum|Optional $sort;
|
public MediaReviewsSortEnum|Optional $sort;
|
||||||
|
@ -2,20 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Dto;
|
namespace App\Dto;
|
||||||
|
|
||||||
use App\Dto\Concerns\MapsDefaultLimitParameter;
|
use App\Dto\Concerns\HasLimitParameter;
|
||||||
use App\Rules\Attributes\MaxLimitWithFallback;
|
use App\Dto\Concerns\HasPageParameter;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\Min;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
|
||||||
use Spatie\LaravelData\Data;
|
use Spatie\LaravelData\Data;
|
||||||
|
|
||||||
abstract class QueryTopItemsCommand extends Data
|
abstract class QueryTopItemsCommand extends Data
|
||||||
{
|
{
|
||||||
use MapsDefaultLimitParameter;
|
use HasLimitParameter, HasPageParameter;
|
||||||
|
|
||||||
#[Numeric, Min(1)]
|
|
||||||
public int|Optional $page = 1;
|
|
||||||
|
|
||||||
#[Numeric, Min(1), MaxLimitWithFallback]
|
|
||||||
public int|Optional $limit;
|
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,9 @@ use App\Contracts\DataRequest;
|
|||||||
use App\Enums\MangaTypeEnum;
|
use App\Enums\MangaTypeEnum;
|
||||||
use App\Enums\TopMangaFilterEnum;
|
use App\Enums\TopMangaFilterEnum;
|
||||||
use App\Http\Resources\V4\MangaCollection;
|
use App\Http\Resources\V4\MangaCollection;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\Validation\Rule;
|
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements DataRequest<MangaCollection>
|
* @implements DataRequest<MangaCollection>
|
||||||
|
@ -3,17 +3,12 @@
|
|||||||
namespace App\Dto;
|
namespace App\Dto;
|
||||||
|
|
||||||
use App\Casts\EnumCast;
|
use App\Casts\EnumCast;
|
||||||
use App\Dto\Concerns\MapsDefaultLimitParameter;
|
use App\Dto\Concerns\HasLimitParameter;
|
||||||
|
use App\Dto\Concerns\HasPageParameter;
|
||||||
use App\Enums\SortDirection;
|
use App\Enums\SortDirection;
|
||||||
use App\Rules\Attributes\MaxLimitWithFallback;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\MapInputName;
|
|
||||||
use Spatie\LaravelData\Attributes\MapOutputName;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\Alpha;
|
use Spatie\LaravelData\Attributes\Validation\Alpha;
|
||||||
use Spatie\LaravelData\Attributes\Validation\IntegerType;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\Max;
|
use Spatie\LaravelData\Attributes\Validation\Max;
|
||||||
use Spatie\LaravelData\Attributes\Validation\Min;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
|
||||||
use Spatie\LaravelData\Attributes\Validation\Size;
|
use Spatie\LaravelData\Attributes\Validation\Size;
|
||||||
use Spatie\LaravelData\Attributes\Validation\StringType;
|
use Spatie\LaravelData\Attributes\Validation\StringType;
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
@ -22,7 +17,7 @@ use Spatie\LaravelData\Optional;
|
|||||||
|
|
||||||
class SearchCommand extends Data
|
class SearchCommand extends Data
|
||||||
{
|
{
|
||||||
use MapsDefaultLimitParameter;
|
use HasLimitParameter, HasPageParameter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The search keywords
|
* The search keywords
|
||||||
@ -31,12 +26,6 @@ class SearchCommand extends Data
|
|||||||
#[Max(255), StringType]
|
#[Max(255), StringType]
|
||||||
public string|Optional $q;
|
public string|Optional $q;
|
||||||
|
|
||||||
#[Numeric, Min(1)]
|
|
||||||
public int|Optional $page = 1;
|
|
||||||
|
|
||||||
#[IntegerType, Min(1), MaxLimitWithFallback]
|
|
||||||
public int|Optional $limit;
|
|
||||||
|
|
||||||
#[WithCast(EnumCast::class, SortDirection::class)]
|
#[WithCast(EnumCast::class, SortDirection::class)]
|
||||||
public SortDirection|Optional $sort;
|
public SortDirection|Optional $sort;
|
||||||
|
|
||||||
|
13
app/Dto/UserAboutLookupCommand.php
Normal file
13
app/Dto/UserAboutLookupCommand.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserAboutLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
}
|
13
app/Dto/UserClubsLookupCommand.php
Normal file
13
app/Dto/UserClubsLookupCommand.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserClubsLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
}
|
13
app/Dto/UserExternalLookupCommand.php
Normal file
13
app/Dto/UserExternalLookupCommand.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserExternalLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
}
|
13
app/Dto/UserFavoritesLookupCommand.php
Normal file
13
app/Dto/UserFavoritesLookupCommand.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserFavoritesLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
}
|
15
app/Dto/UserFriendsLookupCommand.php
Normal file
15
app/Dto/UserFriendsLookupCommand.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Dto\Concerns\HasPageParameter;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserFriendsLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
use HasPageParameter;
|
||||||
|
}
|
13
app/Dto/UserFullLookupCommand.php
Normal file
13
app/Dto/UserFullLookupCommand.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserFullLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
}
|
27
app/Dto/UserHistoryLookupCommand.php
Normal file
27
app/Dto/UserHistoryLookupCommand.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Casts\EnumCast;
|
||||||
|
use App\Enums\UserHistoryTypeEnum;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
|
use Spatie\LaravelData\Attributes\Validation\Nullable;
|
||||||
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserHistoryLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
#[WithCast(EnumCast::class, UserHistoryTypeEnum::class)]
|
||||||
|
public ?UserHistoryTypeEnum $type;
|
||||||
|
|
||||||
|
public static function rules(...$args): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
"type" => [new EnumRule(UserHistoryTypeEnum::class), new Nullable()]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
13
app/Dto/UserProfileLookupCommand.php
Normal file
13
app/Dto/UserProfileLookupCommand.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserProfileLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
}
|
15
app/Dto/UserRecommendationsLookupCommand.php
Normal file
15
app/Dto/UserRecommendationsLookupCommand.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Dto\Concerns\HasPageParameter;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserRecommendationsLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
use HasPageParameter;
|
||||||
|
}
|
15
app/Dto/UserReviewsLookupCommand.php
Normal file
15
app/Dto/UserReviewsLookupCommand.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Dto\Concerns\HasPageParameter;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserReviewsLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
use HasPageParameter;
|
||||||
|
}
|
13
app/Dto/UserStatisticsLookupCommand.php
Normal file
13
app/Dto/UserStatisticsLookupCommand.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserStatisticsLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
}
|
13
app/Dto/UserUpdatesLookupCommand.php
Normal file
13
app/Dto/UserUpdatesLookupCommand.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends LookupDataCommand<JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserUpdatesLookupCommand extends LookupByUsernameCommand
|
||||||
|
{
|
||||||
|
}
|
@ -7,10 +7,10 @@ use App\Concerns\HasRequestFingerprint;
|
|||||||
use App\Contracts\DataRequest;
|
use App\Contracts\DataRequest;
|
||||||
use App\Enums\GenderEnum;
|
use App\Enums\GenderEnum;
|
||||||
use App\Http\Resources\V4\UserCollection;
|
use App\Http\Resources\V4\UserCollection;
|
||||||
use Illuminate\Support\Optional;
|
|
||||||
use Spatie\Enum\Laravel\Rules\EnumRule;
|
use Spatie\Enum\Laravel\Rules\EnumRule;
|
||||||
use Spatie\LaravelData\Attributes\Validation\StringType;
|
use Spatie\LaravelData\Attributes\Validation\StringType;
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements DataRequest<UserCollection>
|
* @implements DataRequest<UserCollection>
|
||||||
|
14
app/Enums/UserHistoryTypeEnum.php
Normal file
14
app/Enums/UserHistoryTypeEnum.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
|
||||||
|
use Spatie\Enum\Laravel\Enum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method static self anime()
|
||||||
|
* @method static self manga()
|
||||||
|
*/
|
||||||
|
final class UserHistoryTypeEnum extends Enum
|
||||||
|
{
|
||||||
|
}
|
29
app/Features/QueryRecentlyOnlineUsersHandler.php
Normal file
29
app/Features/QueryRecentlyOnlineUsersHandler.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\QueryRecentlyOnlineUsersCommand;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use App\Support\CachedData;
|
||||||
|
use Jikan\MyAnimeList\MalClient;
|
||||||
|
use Jikan\Request\User\RecentlyOnlineUsersRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends RequestHandlerWithScraperCache<QueryRecentlyOnlineUsersCommand, JsonResponse>
|
||||||
|
*/
|
||||||
|
final class QueryRecentlyOnlineUsersHandler extends RequestHandlerWithScraperCache
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return QueryRecentlyOnlineUsersCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
|
||||||
|
{
|
||||||
|
return $this->scraperService->findList(
|
||||||
|
$requestFingerPrint,
|
||||||
|
fn(MalClient $jikan, ?int $page = null) => ["results" => $jikan->getRecentOnlineUsers(new RecentlyOnlineUsersRequest())]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
24
app/Features/UserAboutLookupHandler.php
Normal file
24
app/Features/UserAboutLookupHandler.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserAboutLookupCommand;
|
||||||
|
use App\Http\Resources\V4\ProfileAboutResource;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends UserLookupHandler<UserAboutLookupCommand>
|
||||||
|
*/
|
||||||
|
final class UserAboutLookupHandler extends UserLookupHandler
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserAboutLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resource(Collection $results): JsonResource
|
||||||
|
{
|
||||||
|
return new ProfileAboutResource($results->first());
|
||||||
|
}
|
||||||
|
}
|
30
app/Features/UserClubsLookupHandler.php
Normal file
30
app/Features/UserClubsLookupHandler.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserClubsLookupCommand;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use App\Support\CachedData;
|
||||||
|
use Jikan\MyAnimeList\MalClient;
|
||||||
|
use Jikan\Request\User\UserClubsRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends RequestHandlerWithScraperCache<UserClubsLookupCommand, JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserClubsLookupHandler extends RequestHandlerWithScraperCache
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserClubsLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
|
||||||
|
{
|
||||||
|
$username = $requestParams->get("username");
|
||||||
|
return $this->scraperService->findList(
|
||||||
|
$requestFingerPrint,
|
||||||
|
fn(MalClient $jikan, ?int $page = null) => ["results" => $jikan->getUserClubs(new UserClubsRequest($username))]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
24
app/Features/UserExternalLookupHandler.php
Normal file
24
app/Features/UserExternalLookupHandler.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserExternalLookupCommand;
|
||||||
|
use App\Http\Resources\V4\ExternalLinksResource;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends UserLookupHandler<UserExternalLookupCommand>
|
||||||
|
*/
|
||||||
|
final class UserExternalLookupHandler extends UserLookupHandler
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserExternalLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resource(Collection $results): JsonResource
|
||||||
|
{
|
||||||
|
return new ExternalLinksResource($results->first());
|
||||||
|
}
|
||||||
|
}
|
24
app/Features/UserFavoritesLookupHandler.php
Normal file
24
app/Features/UserFavoritesLookupHandler.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserFavoritesLookupCommand;
|
||||||
|
use App\Http\Resources\V4\ProfileFavoritesResource;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends UserLookupHandler<UserFavoritesLookupCommand>
|
||||||
|
*/
|
||||||
|
final class UserFavoritesLookupHandler extends UserLookupHandler
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserFavoritesLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resource(Collection $results): JsonResource
|
||||||
|
{
|
||||||
|
return new ProfileFavoritesResource($results->first());
|
||||||
|
}
|
||||||
|
}
|
31
app/Features/UserFriendsLookupHandler.php
Normal file
31
app/Features/UserFriendsLookupHandler.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserFriendsLookupCommand;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use App\Support\CachedData;
|
||||||
|
use Jikan\MyAnimeList\MalClient;
|
||||||
|
use Jikan\Request\User\UserFriendsRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends RequestHandlerWithScraperCache<UserFriendsLookupCommand, JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserFriendsLookupHandler extends RequestHandlerWithScraperCache
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserFriendsLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
|
||||||
|
{
|
||||||
|
$username = $requestParams->get("username");
|
||||||
|
return $this->scraperService->findList(
|
||||||
|
$requestFingerPrint,
|
||||||
|
fn(MalClient $jikan, ?int $page = null) => $jikan->getUserFriends(new UserFriendsRequest($username, $page)),
|
||||||
|
$requestParams->get("page", 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
24
app/Features/UserFullLookupHandler.php
Normal file
24
app/Features/UserFullLookupHandler.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserFullLookupCommand;
|
||||||
|
use App\Http\Resources\V4\ProfileFullResource;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends UserLookupHandler<UserFullLookupCommand>
|
||||||
|
*/
|
||||||
|
final class UserFullLookupHandler extends UserLookupHandler
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserFullLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resource(Collection $results): JsonResource
|
||||||
|
{
|
||||||
|
return new ProfileFullResource($results->first());
|
||||||
|
}
|
||||||
|
}
|
39
app/Features/UserHistoryLookupHandler.php
Normal file
39
app/Features/UserHistoryLookupHandler.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserHistoryLookupCommand;
|
||||||
|
use App\Http\Resources\V4\ProfileHistoryResource;
|
||||||
|
use App\Support\CachedData;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Jikan\MyAnimeList\MalClient;
|
||||||
|
use Jikan\Request\User\UserHistoryRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends RequestHandlerWithScraperCache<UserHistoryLookupCommand>
|
||||||
|
*/
|
||||||
|
final class UserHistoryLookupHandler extends RequestHandlerWithScraperCache
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserHistoryLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resource(Collection $results): JsonResource
|
||||||
|
{
|
||||||
|
return new ProfileHistoryResource($results->first());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
|
||||||
|
{
|
||||||
|
$type = $requestParams->get("type");
|
||||||
|
$username = $requestParams->get("username");
|
||||||
|
return $this->scraperService->findList(
|
||||||
|
$requestFingerPrint,
|
||||||
|
fn(MalClient $jikan, ?int $page = null) => ["history" => $jikan->getUserHistory(new UserHistoryRequest(
|
||||||
|
$username, $type
|
||||||
|
))]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
26
app/Features/UserLookupHandler.php
Normal file
26
app/Features/UserLookupHandler.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use App\Support\CachedData;
|
||||||
|
use Jikan\MyAnimeList\MalClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template TRequest
|
||||||
|
* @extends RequestHandlerWithScraperCache<TRequest, JsonResponse>
|
||||||
|
*/
|
||||||
|
abstract class UserLookupHandler extends RequestHandlerWithScraperCache
|
||||||
|
{
|
||||||
|
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
|
||||||
|
{
|
||||||
|
$username = $requestParams->get("username");
|
||||||
|
return $this->scraperService->findByKey(
|
||||||
|
"username",
|
||||||
|
$username,
|
||||||
|
$requestFingerPrint,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
24
app/Features/UserProfileLookupHandler.php
Normal file
24
app/Features/UserProfileLookupHandler.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserProfileLookupCommand;
|
||||||
|
use App\Http\Resources\V4\ProfileResource;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends UserLookupHandler<UserProfileLookupCommand>
|
||||||
|
*/
|
||||||
|
final class UserProfileLookupHandler extends UserLookupHandler
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserProfileLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resource(Collection $results): JsonResource
|
||||||
|
{
|
||||||
|
return new ProfileResource($results->first());
|
||||||
|
}
|
||||||
|
}
|
31
app/Features/UserRecommendationsLookupHandler.php
Normal file
31
app/Features/UserRecommendationsLookupHandler.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserRecommendationsLookupCommand;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use App\Support\CachedData;
|
||||||
|
use Jikan\MyAnimeList\MalClient;
|
||||||
|
use Jikan\Request\User\UserRecommendationsRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends RequestHandlerWithScraperCache<UserRecommendationsLookupCommand, JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserRecommendationsLookupHandler extends RequestHandlerWithScraperCache
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserRecommendationsLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
|
||||||
|
{
|
||||||
|
$username = $requestParams->get("username");
|
||||||
|
return $this->scraperService->findList(
|
||||||
|
$requestFingerPrint,
|
||||||
|
fn(MalClient $jikan, ?int $page = null) => $jikan->getUserRecommendations(new UserRecommendationsRequest($username, $page)),
|
||||||
|
$requestParams->get("page", 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
36
app/Features/UserReviewsLookupHandler.php
Normal file
36
app/Features/UserReviewsLookupHandler.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserReviewsLookupCommand;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use App\Support\CachedData;
|
||||||
|
use Jikan\MyAnimeList\MalClient;
|
||||||
|
use Jikan\Request\User\UserReviewsRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends RequestHandlerWithScraperCache<UserReviewsLookupCommand, JsonResponse>
|
||||||
|
*/
|
||||||
|
final class UserReviewsLookupHandler extends RequestHandlerWithScraperCache
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserReviewsLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
|
||||||
|
{
|
||||||
|
$username = $requestParams->get("username");
|
||||||
|
return $this->scraperService->findList(
|
||||||
|
$requestFingerPrint,
|
||||||
|
fn(MalClient $jikan, ?int $page = null) => $jikan->getUserReviews(
|
||||||
|
new UserReviewsRequest(
|
||||||
|
$username,
|
||||||
|
$page,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
$requestParams->get("page", 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
24
app/Features/UserStatisticsLookupHandler.php
Normal file
24
app/Features/UserStatisticsLookupHandler.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserStatisticsLookupCommand;
|
||||||
|
use App\Http\Resources\V4\ProfileStatisticsResource;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends UserLookupHandler<UserStatisticsLookupCommand>
|
||||||
|
*/
|
||||||
|
final class UserStatisticsLookupHandler extends UserLookupHandler
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserStatisticsLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resource(Collection $results): JsonResource
|
||||||
|
{
|
||||||
|
return new ProfileStatisticsResource($results->first());
|
||||||
|
}
|
||||||
|
}
|
24
app/Features/UserUpdatesLookupHandler.php
Normal file
24
app/Features/UserUpdatesLookupHandler.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Features;
|
||||||
|
|
||||||
|
use App\Dto\UserUpdatesLookupCommand;
|
||||||
|
use App\Http\Resources\V4\ProfileLastUpdatesResource;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends UserLookupHandler<UserUpdatesLookupCommand>
|
||||||
|
*/
|
||||||
|
final class UserUpdatesLookupHandler extends UserLookupHandler
|
||||||
|
{
|
||||||
|
public function requestClass(): string
|
||||||
|
{
|
||||||
|
return UserUpdatesLookupCommand::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resource(Collection $results): JsonResource
|
||||||
|
{
|
||||||
|
return new ProfileLastUpdatesResource($results->first());
|
||||||
|
}
|
||||||
|
}
|
@ -1,37 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\V4DB\Traits;
|
|
||||||
|
|
||||||
use App\Providers\SearchQueryBuilderProvider;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
trait JikanApiQueryBuilder
|
|
||||||
{
|
|
||||||
private SearchQueryBuilderProvider $searchQueryBuilderProvider;
|
|
||||||
|
|
||||||
protected function getQueryBuilder(string $name, Request $request): \Illuminate\Database\Eloquent\Builder|\Laravel\Scout\Builder
|
|
||||||
{
|
|
||||||
$queryBuilder = $this->searchQueryBuilderProvider->getQueryBuilder($name);
|
|
||||||
return $queryBuilder->query($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getPaginator(string $name, Request $request, \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $results): \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
|
||||||
{
|
|
||||||
$queryBuilder = $this->searchQueryBuilderProvider->getQueryBuilder($name);
|
|
||||||
return $queryBuilder->paginateBuilder($request, $results);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @template T
|
|
||||||
* @param class-string<T> $resourceCollectionClass
|
|
||||||
* @param string $resourceTypeName
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @return T
|
|
||||||
*/
|
|
||||||
protected function preparePaginatedResponse(string $resourceCollectionClass, string $resourceTypeName, Request $request)
|
|
||||||
{
|
|
||||||
$results = $this->getQueryBuilder($resourceTypeName, $request);
|
|
||||||
$paginator = $this->getPaginator($resourceTypeName, $request, $results);
|
|
||||||
return new $resourceCollectionClass($paginator);
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,29 +2,20 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\V4DB;
|
namespace App\Http\Controllers\V4DB;
|
||||||
|
|
||||||
use App\Http\HttpResponse;
|
use App\Dto\QueryRecentlyOnlineUsersCommand;
|
||||||
use App\Http\QueryBuilder\UserListQueryBuilder;
|
use App\Dto\UserAboutLookupCommand;
|
||||||
use App\Http\Resources\V4\ExternalLinksResource;
|
use App\Dto\UserClubsLookupCommand;
|
||||||
use App\Http\Resources\V4\ProfileHistoryResource;
|
use App\Dto\UserExternalLookupCommand;
|
||||||
use App\Http\Resources\V4\ResultsResource;
|
use App\Dto\UserFavoritesLookupCommand;
|
||||||
use App\Http\Resources\V4\UserProfileAnimeListCollection;
|
use App\Dto\UserFriendsLookupCommand;
|
||||||
use App\Http\Resources\V4\UserProfileAnimeListResource;
|
use App\Dto\UserFullLookupCommand;
|
||||||
use App\Http\Resources\V4\UserProfileMangaListCollection;
|
use App\Dto\UserHistoryLookupCommand;
|
||||||
use App\Http\Resources\V4\UserProfileMangaListResource;
|
use App\Dto\UserProfileLookupCommand;
|
||||||
use App\Profile;
|
use App\Dto\UserRecommendationsLookupCommand;
|
||||||
|
use App\Dto\UserReviewsLookupCommand;
|
||||||
|
use App\Dto\UserStatisticsLookupCommand;
|
||||||
|
use App\Dto\UserUpdatesLookupCommand;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Jikan\Helper\Constants;
|
|
||||||
use Jikan\Request\User\RecentlyOnlineUsersRequest;
|
|
||||||
use Jikan\Request\User\UserAnimeListRequest;
|
|
||||||
use Jikan\Request\User\UserClubsRequest;
|
|
||||||
use Jikan\Request\User\UserFriendsRequest;
|
|
||||||
use Jikan\Request\User\UserHistoryRequest;
|
|
||||||
use Jikan\Request\User\UserMangaListRequest;
|
|
||||||
use Jikan\Request\User\UserRecommendationsRequest;
|
|
||||||
use Jikan\Request\User\UserReviewsRequest;
|
|
||||||
use MongoDB\BSON\UTCDateTime;
|
|
||||||
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Controller
|
* Class Controller
|
||||||
@ -62,61 +53,9 @@ class UserController extends Controller
|
|||||||
* ),
|
* ),
|
||||||
* ),
|
* ),
|
||||||
*/
|
*/
|
||||||
public function full(Request $request, string $username)
|
public function full(UserFullLookupCommand $command)
|
||||||
{
|
{
|
||||||
$username = strtolower($username);
|
return $this->mediator->send($command);
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$response = Profile::scrape($username);
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
$meta = [
|
|
||||||
'createdAt' => new UTCDateTime(),
|
|
||||||
'modifiedAt' => new UTCDateTime(),
|
|
||||||
'request_hash' => $this->fingerprint,
|
|
||||||
'internal_username' => $username
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$meta['modifiedAt'] = new UTCDateTime();
|
|
||||||
|
|
||||||
$response = $meta + $response;
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
Profile::query()
|
|
||||||
->insert($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->isExpired($request, $results)) {
|
|
||||||
Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->update($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
return HttpResponse::notFound($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new \App\Http\Resources\V4\ProfileFullResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,61 +87,9 @@ class UserController extends Controller
|
|||||||
* ),
|
* ),
|
||||||
* ),
|
* ),
|
||||||
*/
|
*/
|
||||||
public function profile(Request $request, string $username)
|
public function profile(UserProfileLookupCommand $command)
|
||||||
{
|
{
|
||||||
$username = strtolower($username);
|
return $this->mediator->send($command);
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$response = Profile::scrape($username);
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
$meta = [
|
|
||||||
'createdAt' => new UTCDateTime(),
|
|
||||||
'modifiedAt' => new UTCDateTime(),
|
|
||||||
'request_hash' => $this->fingerprint,
|
|
||||||
'internal_username' => $username
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$meta['modifiedAt'] = new UTCDateTime();
|
|
||||||
|
|
||||||
$response = $meta + $response;
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
Profile::query()
|
|
||||||
->insert($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->isExpired($request, $results)) {
|
|
||||||
Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->update($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
return HttpResponse::notFound($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new \App\Http\Resources\V4\ProfileResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -231,62 +118,9 @@ class UserController extends Controller
|
|||||||
* ),
|
* ),
|
||||||
* ),
|
* ),
|
||||||
*/
|
*/
|
||||||
public function statistics(Request $request, string $username)
|
public function statistics(UserStatisticsLookupCommand $command)
|
||||||
{
|
{
|
||||||
|
return $this->mediator->send($command);
|
||||||
$username = strtolower($username);
|
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$response = Profile::scrape($username);
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
$meta = [
|
|
||||||
'createdAt' => new UTCDateTime(),
|
|
||||||
'modifiedAt' => new UTCDateTime(),
|
|
||||||
'request_hash' => $this->fingerprint,
|
|
||||||
'internal_username' => $username
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$meta['modifiedAt'] = new UTCDateTime();
|
|
||||||
|
|
||||||
$response = $meta + $response;
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
Profile::query()
|
|
||||||
->insert($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->isExpired($request, $results)) {
|
|
||||||
Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->update($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
return HttpResponse::notFound($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new \App\Http\Resources\V4\ProfileStatisticsResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -319,62 +153,9 @@ class UserController extends Controller
|
|||||||
* ),
|
* ),
|
||||||
* ),
|
* ),
|
||||||
*/
|
*/
|
||||||
public function favorites(Request $request, string $username)
|
public function favorites(UserFavoritesLookupCommand $command)
|
||||||
{
|
{
|
||||||
|
return $this->mediator->send($command);
|
||||||
$username = strtolower($username);
|
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$response = Profile::scrape($username);
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
$meta = [
|
|
||||||
'createdAt' => new UTCDateTime(),
|
|
||||||
'modifiedAt' => new UTCDateTime(),
|
|
||||||
'request_hash' => $this->fingerprint,
|
|
||||||
'internal_username' => $username
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$meta['modifiedAt'] = new UTCDateTime();
|
|
||||||
|
|
||||||
$response = $meta + $response;
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
Profile::query()
|
|
||||||
->insert($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->isExpired($request, $results)) {
|
|
||||||
Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->update($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
return HttpResponse::notFound($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new \App\Http\Resources\V4\ProfileFavoritesResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -403,62 +184,9 @@ class UserController extends Controller
|
|||||||
* ),
|
* ),
|
||||||
* ),
|
* ),
|
||||||
*/
|
*/
|
||||||
public function userupdates(Request $request, string $username)
|
public function userupdates(UserUpdatesLookupCommand $command)
|
||||||
{
|
{
|
||||||
|
return $this->mediator->send($command);
|
||||||
$username = strtolower($username);
|
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$response = Profile::scrape($username);
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
$meta = [
|
|
||||||
'createdAt' => new UTCDateTime(),
|
|
||||||
'modifiedAt' => new UTCDateTime(),
|
|
||||||
'request_hash' => $this->fingerprint,
|
|
||||||
'internal_username' => $username
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$meta['modifiedAt'] = new UTCDateTime();
|
|
||||||
|
|
||||||
$response = $meta + $response;
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
Profile::query()
|
|
||||||
->insert($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->isExpired($request, $results)) {
|
|
||||||
Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->update($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
return HttpResponse::notFound($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new \App\Http\Resources\V4\ProfileLastUpdatesResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -487,62 +215,9 @@ class UserController extends Controller
|
|||||||
* ),
|
* ),
|
||||||
* ),
|
* ),
|
||||||
*/
|
*/
|
||||||
public function about(Request $request, string $username)
|
public function about(UserAboutLookupCommand $command)
|
||||||
{
|
{
|
||||||
|
return $this->mediator->send($command);
|
||||||
$username = strtolower($username);
|
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$response = Profile::scrape($username);
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
$meta = [
|
|
||||||
'createdAt' => new UTCDateTime(),
|
|
||||||
'modifiedAt' => new UTCDateTime(),
|
|
||||||
'request_hash' => $this->fingerprint,
|
|
||||||
'internal_username' => $username
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$meta['modifiedAt'] = new UTCDateTime();
|
|
||||||
|
|
||||||
$response = $meta + $response;
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
Profile::query()
|
|
||||||
->insert($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->isExpired($request, $results)) {
|
|
||||||
Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->update($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
return HttpResponse::notFound($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new \App\Http\Resources\V4\ProfileAboutResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -578,45 +253,9 @@ class UserController extends Controller
|
|||||||
* ),
|
* ),
|
||||||
* ),
|
* ),
|
||||||
*/
|
*/
|
||||||
public function history(Request $request, string $username, ?string $type = null)
|
public function history(UserHistoryLookupCommand $command)
|
||||||
{
|
{
|
||||||
$filter = $request->get('filter') ?? null;
|
return $this->mediator->send($command);
|
||||||
|
|
||||||
if (!is_null($type)) {
|
|
||||||
$type = strtolower($type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_null($filter) && is_null($type)) {
|
|
||||||
$type = strtolower($filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_null($type) && !\in_array($type, ['anime', 'manga'])) {
|
|
||||||
return HttpResponse::badRequest($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = DB::table($this->getRouteTable($request))
|
|
||||||
->where('request_hash', $this->fingerprint)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$data = ['history'=>$this->jikan->getUserHistory(new UserHistoryRequest($username, $type))];
|
|
||||||
$response = \json_decode($this->serializer->serialize($data, 'json'), true);
|
|
||||||
|
|
||||||
$results = $this->updateCache($request, $results, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new ProfileHistoryResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -690,32 +329,9 @@ class UserController extends Controller
|
|||||||
* }
|
* }
|
||||||
* ),
|
* ),
|
||||||
*/
|
*/
|
||||||
public function friends(Request $request, string $username)
|
public function friends(UserFriendsLookupCommand $command)
|
||||||
{
|
{
|
||||||
$results = DB::table($this->getRouteTable($request))
|
return $this->mediator->send($command);
|
||||||
->where('request_hash', $this->fingerprint)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$page = $request->get('page') ?? 1;
|
|
||||||
$data = $this->jikan->getUserFriends(new UserFriendsRequest($username, $page));
|
|
||||||
$response = \json_decode($this->serializer->serialize($data, 'json'), true);
|
|
||||||
|
|
||||||
$results = $this->updateCache($request, $results, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new ResultsResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -748,51 +364,8 @@ class UserController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function animelist(Request $request, string $username, ?string $status = null)
|
public function animelist(Request $request, string $username, ?string $status = null)
|
||||||
{
|
{
|
||||||
if (!is_null($status)) {
|
// noop, intentionally left blank
|
||||||
$status = strtolower($status);
|
// todo: remove as this is obsolete
|
||||||
|
|
||||||
if (!\in_array($status, ['all', 'watching', 'completed', 'onhold', 'dropped', 'plantowatch'])) {
|
|
||||||
return HttpResponse::badRequest($request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$status = $this->listStatusToId($status);
|
|
||||||
|
|
||||||
|
|
||||||
$results = DB::table($this->getRouteTable($request))
|
|
||||||
->where('request_hash', $this->fingerprint)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$page = $request->get('page') ?? 1;
|
|
||||||
$data = $this->jikan->getUserAnimeList(
|
|
||||||
UserListQueryBuilder::create(
|
|
||||||
$request,
|
|
||||||
new UserAnimeListRequest($username, $page, $status)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$response = ['anime' => \json_decode($this->serializer->serialize($data, 'json'), true)];
|
|
||||||
|
|
||||||
$results = $this->updateCache($request, $results, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$listResults = $results->first()['anime'];
|
|
||||||
|
|
||||||
foreach ($listResults as &$result) {
|
|
||||||
$result = (new UserProfileAnimeListResource($result));
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new UserProfileAnimeListCollection(
|
|
||||||
$listResults
|
|
||||||
))->response($request);
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -825,52 +398,8 @@ class UserController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function mangalist(Request $request, string $username, ?string $status = null)
|
public function mangalist(Request $request, string $username, ?string $status = null)
|
||||||
{
|
{
|
||||||
if (!is_null($status)) {
|
// noop, intentionally left blank
|
||||||
$status = strtolower($status);
|
// todo: remove as this is obsolete
|
||||||
|
|
||||||
if (!\in_array($status, ['all', 'reading', 'completed', 'onhold', 'dropped', 'plantoread', 'ptr'])) {
|
|
||||||
return response()->json([
|
|
||||||
'error' => 'Bad Request'
|
|
||||||
])->setStatusCode(400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$status = $this->listStatusToId($status);
|
|
||||||
|
|
||||||
$results = DB::table($this->getRouteTable($request))
|
|
||||||
->where('request_hash', $this->fingerprint)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$page = $request->get('page') ?? 1;
|
|
||||||
$data = $this->jikan->getUserMangaList(
|
|
||||||
UserListQueryBuilder::create(
|
|
||||||
$request,
|
|
||||||
new UserMangaListRequest($username, $page, $status)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$response = ['manga' => \json_decode($this->serializer->serialize($data, 'json'), true)];
|
|
||||||
|
|
||||||
$results = $this->updateCache($request, $results, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$listResults = $results->first()['manga'];
|
|
||||||
|
|
||||||
foreach ($listResults as &$result) {
|
|
||||||
$result = (new UserProfileMangaListResource($result));
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new UserProfileMangaListCollection(
|
|
||||||
$listResults
|
|
||||||
))->response($request);
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -955,39 +484,9 @@ class UserController extends Controller
|
|||||||
* ),
|
* ),
|
||||||
* ),
|
* ),
|
||||||
*/
|
*/
|
||||||
public function reviews(Request $request, string $username)
|
public function reviews(UserReviewsLookupCommand $command)
|
||||||
{
|
{
|
||||||
$results = DB::table($this->getRouteTable($request))
|
return $this->mediator->send($command);
|
||||||
->where('request_hash', $this->fingerprint)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$page = $request->get('page') ?? 1;
|
|
||||||
|
|
||||||
$data = $this->jikan
|
|
||||||
->getUserReviews(
|
|
||||||
new UserReviewsRequest(
|
|
||||||
$username,
|
|
||||||
$page,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$response = \json_decode($this->serializer->serialize($data, 'json'), true);
|
|
||||||
$results = $this->updateCache($request, $results, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new ResultsResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1017,32 +516,9 @@ class UserController extends Controller
|
|||||||
* ),
|
* ),
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function recommendations(Request $request, string $username)
|
public function recommendations(UserRecommendationsLookupCommand $command)
|
||||||
{
|
{
|
||||||
$results = DB::table($this->getRouteTable($request))
|
return $this->mediator->send($command);
|
||||||
->where('request_hash', $this->fingerprint)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$page = $request->get('page') ?? 1;
|
|
||||||
$data = $this->jikan->getUserRecommendations(new UserRecommendationsRequest($username, $page));
|
|
||||||
$response = \json_decode($this->serializer->serialize($data, 'json'), true);
|
|
||||||
|
|
||||||
$results = $this->updateCache($request, $results, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new ResultsResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1106,31 +582,9 @@ class UserController extends Controller
|
|||||||
* }
|
* }
|
||||||
* ),
|
* ),
|
||||||
*/
|
*/
|
||||||
public function clubs(Request $request, string $username)
|
public function clubs(UserClubsLookupCommand $command)
|
||||||
{
|
{
|
||||||
$results = DB::table($this->getRouteTable($request))
|
return $this->mediator->send($command);
|
||||||
->where('request_hash', $this->fingerprint)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$data = ['results' => $this->jikan->getUserClubs(new UserClubsRequest($username))];
|
|
||||||
$response = \json_decode($this->serializer->serialize($data, 'json'), true);
|
|
||||||
|
|
||||||
$results = $this->updateCache($request, $results, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new ResultsResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1160,125 +614,13 @@ class UserController extends Controller
|
|||||||
* ),
|
* ),
|
||||||
* ),
|
* ),
|
||||||
*/
|
*/
|
||||||
public function external(Request $request, string $username)
|
public function external(UserExternalLookupCommand $command)
|
||||||
{
|
{
|
||||||
$username = strtolower($username);
|
return $this->mediator->send($command);
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$response = Profile::scrape($username);
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
$meta = [
|
|
||||||
'createdAt' => new UTCDateTime(),
|
|
||||||
'modifiedAt' => new UTCDateTime(),
|
|
||||||
'request_hash' => $this->fingerprint,
|
|
||||||
'internal_username' => $username
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$meta['modifiedAt'] = new UTCDateTime();
|
|
||||||
|
|
||||||
$response = $meta + $response;
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
Profile::query()
|
|
||||||
->insert($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->isExpired($request, $results)) {
|
|
||||||
Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->update($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = Profile::query()
|
|
||||||
->where('internal_username', $username)
|
|
||||||
->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($results->isEmpty()) {
|
|
||||||
return HttpResponse::notFound($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new ExternalLinksResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function recentlyOnline(QueryRecentlyOnlineUsersCommand $command)
|
||||||
* @param Request $request
|
|
||||||
* @return mixed
|
|
||||||
* @throws \Jikan\Exception\BadResponseException
|
|
||||||
* @throws \Jikan\Exception\ParserException
|
|
||||||
*/
|
|
||||||
public function recentlyOnline(Request $request)
|
|
||||||
{
|
{
|
||||||
$results = DB::table($this->getRouteTable($request))
|
return $this->mediator->send($command);
|
||||||
->where('request_hash', $this->fingerprint)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if (
|
|
||||||
$results->isEmpty()
|
|
||||||
|| $this->isExpired($request, $results)
|
|
||||||
) {
|
|
||||||
$data = ['results'=>$this->jikan->getRecentOnlineUsers(new RecentlyOnlineUsersRequest())];
|
|
||||||
$response = \json_decode($this->serializer->serialize($data, 'json'), true);
|
|
||||||
|
|
||||||
$results = $this->updateCache($request, $results, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = (new ResultsResource(
|
|
||||||
$results->first()
|
|
||||||
))->response();
|
|
||||||
|
|
||||||
return $this->prepareResponse(
|
|
||||||
$response,
|
|
||||||
$results,
|
|
||||||
$request
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string|null $status
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
private function listStatusToId(?string $status) : int
|
|
||||||
{
|
|
||||||
if (is_null($status)) {
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($status) {
|
|
||||||
case 'all':
|
|
||||||
return 7;
|
|
||||||
case 'watching':
|
|
||||||
case 'reading':
|
|
||||||
return 1;
|
|
||||||
case 'completed':
|
|
||||||
return 2;
|
|
||||||
case 'onhold':
|
|
||||||
return 3;
|
|
||||||
case 'dropped':
|
|
||||||
return 4;
|
|
||||||
case 'plantowatch':
|
|
||||||
case 'ptw':
|
|
||||||
case 'plantoread':
|
|
||||||
case 'ptr':
|
|
||||||
return 6;
|
|
||||||
default:
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
app/Http/Middleware/EndpointCacheTtlMiddleware.php
Normal file
33
app/Http/Middleware/EndpointCacheTtlMiddleware.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Http\HttpHelper;
|
||||||
|
use App\Support\CacheOptions;
|
||||||
|
use App\Support\JikanConfig;
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middleware which sets the cache ttl globally based on the endpoint's name
|
||||||
|
*/
|
||||||
|
final class EndpointCacheTtlMiddleware
|
||||||
|
{
|
||||||
|
// CacheOptions instance is singleton, so we set the ttl globally
|
||||||
|
public function __construct(private readonly CacheOptions $cacheOptions,
|
||||||
|
private readonly JikanConfig $jikanConfig)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(Request $request, Closure $next)
|
||||||
|
{
|
||||||
|
$routeName = HttpHelper::getRouteName($request);
|
||||||
|
$ttl = $this->jikanConfig->cacheTtlForEndpoint($routeName);
|
||||||
|
$this->cacheOptions->setTtl($ttl);
|
||||||
|
|
||||||
|
$response = $next($request);
|
||||||
|
|
||||||
|
$this->cacheOptions->setTtl(null);
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Macros;
|
namespace App\Macros;
|
||||||
|
|
||||||
use App\Concerns\ScraperCacheTtl;
|
|
||||||
use App\Support\CachedData;
|
use App\Support\CachedData;
|
||||||
|
use App\Support\CacheOptions;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
@ -12,8 +12,6 @@ use Illuminate\Support\Carbon;
|
|||||||
*/
|
*/
|
||||||
final class ResponseJikanCacheFlags
|
final class ResponseJikanCacheFlags
|
||||||
{
|
{
|
||||||
use ScraperCacheTtl;
|
|
||||||
|
|
||||||
public function __invoke(): \Closure
|
public function __invoke(): \Closure
|
||||||
{
|
{
|
||||||
return function (string $cacheKey, CachedData $scraperResults) {
|
return function (string $cacheKey, CachedData $scraperResults) {
|
||||||
@ -22,7 +20,7 @@ final class ResponseJikanCacheFlags
|
|||||||
*/
|
*/
|
||||||
return $this
|
return $this
|
||||||
->header("X-Request-Fingerprint", $cacheKey)
|
->header("X-Request-Fingerprint", $cacheKey)
|
||||||
->setTtl(ResponseJikanCacheFlags::cacheTtl())
|
->setTtl(app(CacheOptions::class)->ttl())
|
||||||
->setExpires(Carbon::createFromTimestamp($scraperResults->expiry()))
|
->setExpires(Carbon::createFromTimestamp($scraperResults->expiry()))
|
||||||
->setLastModified(Carbon::createFromTimestamp($scraperResults->lastModified()));
|
->setLastModified(Carbon::createFromTimestamp($scraperResults->lastModified()));
|
||||||
};
|
};
|
||||||
|
@ -15,22 +15,11 @@ use App\Contracts\Repository;
|
|||||||
use App\Contracts\RequestHandler;
|
use App\Contracts\RequestHandler;
|
||||||
use App\Contracts\UnitOfWork;
|
use App\Contracts\UnitOfWork;
|
||||||
use App\Contracts\UserRepository;
|
use App\Contracts\UserRepository;
|
||||||
use App\GenreAnime;
|
use App\Http\Middleware\EndpointCacheTtlMiddleware;
|
||||||
use App\GenreManga;
|
|
||||||
use App\Http\QueryBuilder\AnimeSearchQueryBuilder;
|
|
||||||
use App\Http\QueryBuilder\CharacterSearchQueryBuilder;
|
|
||||||
use App\Http\QueryBuilder\ClubSearchQueryBuilder;
|
|
||||||
use App\Http\QueryBuilder\PeopleSearchQueryBuilder;
|
|
||||||
use App\Http\QueryBuilder\SimpleSearchQueryBuilder;
|
|
||||||
use App\Http\QueryBuilder\MangaSearchQueryBuilder;
|
|
||||||
use App\Http\QueryBuilder\TopAnimeQueryBuilder;
|
|
||||||
use App\Http\QueryBuilder\TopMangaQueryBuilder;
|
|
||||||
use App\Macros\CollectionOffsetGetFirst;
|
use App\Macros\CollectionOffsetGetFirst;
|
||||||
use App\Macros\ResponseJikanCacheFlags;
|
use App\Macros\ResponseJikanCacheFlags;
|
||||||
use App\Macros\To2dArrayWithDottedKeys;
|
use App\Macros\To2dArrayWithDottedKeys;
|
||||||
use App\Magazine;
|
|
||||||
use App\Mixins\ScoutBuilderMixin;
|
use App\Mixins\ScoutBuilderMixin;
|
||||||
use App\Producers;
|
|
||||||
use App\Repositories\AnimeGenresRepository;
|
use App\Repositories\AnimeGenresRepository;
|
||||||
use App\Repositories\DefaultAnimeRepository;
|
use App\Repositories\DefaultAnimeRepository;
|
||||||
use App\Repositories\DefaultCharacterRepository;
|
use App\Repositories\DefaultCharacterRepository;
|
||||||
@ -53,7 +42,9 @@ use App\Services\ScoutSearchService;
|
|||||||
use App\Services\SearchEngineSearchService;
|
use App\Services\SearchEngineSearchService;
|
||||||
use App\Services\SearchService;
|
use App\Services\SearchService;
|
||||||
use App\Services\TypeSenseScoutSearchService;
|
use App\Services\TypeSenseScoutSearchService;
|
||||||
|
use App\Support\CacheOptions;
|
||||||
use App\Support\DefaultMediator;
|
use App\Support\DefaultMediator;
|
||||||
|
use App\Support\JikanConfig;
|
||||||
use App\Support\JikanUnitOfWork;
|
use App\Support\JikanUnitOfWork;
|
||||||
use Illuminate\Contracts\Container\BindingResolutionException;
|
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
@ -87,6 +78,9 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
*/
|
*/
|
||||||
public function register(): void
|
public function register(): void
|
||||||
{
|
{
|
||||||
|
$this->app->singleton(JikanConfig::class, fn() => new JikanConfig(config("jikan")));
|
||||||
|
// cache options class is used to share the request scope level cache settings
|
||||||
|
$this->app->singleton(CacheOptions::class);
|
||||||
$this->app->singleton(CachedScraperService::class, DefaultCachedScraperService::class);
|
$this->app->singleton(CachedScraperService::class, DefaultCachedScraperService::class);
|
||||||
if ($this->getSearchIndexesEnabledConfig($this->app)) {
|
if ($this->getSearchIndexesEnabledConfig($this->app)) {
|
||||||
$this->app->bind(QueryBuilderPaginatorService::class, ScoutBuilderPaginatorService::class);
|
$this->app->bind(QueryBuilderPaginatorService::class, ScoutBuilderPaginatorService::class);
|
||||||
@ -268,7 +262,20 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
Features\QueryMangaRecommendationsHandler::class => $unitOfWorkInstance->documents("recommendations"),
|
Features\QueryMangaRecommendationsHandler::class => $unitOfWorkInstance->documents("recommendations"),
|
||||||
Features\QueryAnimeReviewsHandler::class => $unitOfWorkInstance->documents("reviews"),
|
Features\QueryAnimeReviewsHandler::class => $unitOfWorkInstance->documents("reviews"),
|
||||||
Features\QueryMangaReviewsHandler::class => $unitOfWorkInstance->documents("reviews"),
|
Features\QueryMangaReviewsHandler::class => $unitOfWorkInstance->documents("reviews"),
|
||||||
Features\QueryAnimeSeasonListHandler::class => $unitOfWorkInstance->documents("season_archive")
|
Features\QueryAnimeSeasonListHandler::class => $unitOfWorkInstance->documents("season_archive"),
|
||||||
|
Features\UserFullLookupHandler::class => $unitOfWorkInstance->users(),
|
||||||
|
Features\UserProfileLookupHandler::class => $unitOfWorkInstance->users(),
|
||||||
|
Features\UserStatisticsLookupHandler::class => $unitOfWorkInstance->users(),
|
||||||
|
Features\UserFavoritesLookupHandler::class => $unitOfWorkInstance->users(),
|
||||||
|
Features\UserUpdatesLookupHandler::class => $unitOfWorkInstance->users(),
|
||||||
|
Features\UserAboutLookupHandler::class => $unitOfWorkInstance->users(),
|
||||||
|
Features\UserHistoryLookupHandler::class => $unitOfWorkInstance->documents("users_history"),
|
||||||
|
Features\UserFriendsLookupHandler::class => $unitOfWorkInstance->documents("users_friends"),
|
||||||
|
Features\UserReviewsLookupHandler::class => $unitOfWorkInstance->documents("users_reviews"),
|
||||||
|
Features\UserRecommendationsLookupHandler::class => $unitOfWorkInstance->documents("users_recommendations"),
|
||||||
|
Features\UserClubsLookupHandler::class => $unitOfWorkInstance->documents("users_clubs"),
|
||||||
|
Features\UserExternalLookupHandler::class => $unitOfWorkInstance->users(),
|
||||||
|
Features\QueryRecentlyOnlineUsersHandler::class => $unitOfWorkInstance->documents("users_recently_online")
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($requestHandlersWithScraperService as $handlerClass => $repositoryInstance) {
|
foreach ($requestHandlersWithScraperService as $handlerClass => $repositoryInstance) {
|
||||||
@ -347,15 +354,11 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
|
|
||||||
public static function servicesToWarm(): array
|
public static function servicesToWarm(): array
|
||||||
{
|
{
|
||||||
|
// todo: test again with roadrunner -- specific issue: typesense driver not loaded in time
|
||||||
$services = [
|
$services = [
|
||||||
ScoutSearchService::class,
|
ScoutSearchService::class,
|
||||||
AnimeSearchQueryBuilder::class,
|
UnitOfWork::class,
|
||||||
MangaSearchQueryBuilder::class,
|
CachedScraperService::class
|
||||||
ClubSearchQueryBuilder::class,
|
|
||||||
CharacterSearchQueryBuilder::class,
|
|
||||||
PeopleSearchQueryBuilder::class,
|
|
||||||
TopAnimeQueryBuilder::class,
|
|
||||||
TopMangaQueryBuilder::class
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (Env::get("SCOUT_DRIVER") === "typesense") {
|
if (Env::get("SCOUT_DRIVER") === "typesense") {
|
||||||
@ -366,6 +369,12 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
$services[] = \Elastic\Elasticsearch\Client::class;
|
$services[] = \Elastic\Elasticsearch\Client::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Env::get("SCOUT_DRIVER") !== "none" && Env::get("SCOUT_DRIVER")) {
|
||||||
|
$services[] = ScoutBuilderPaginatorService::class;
|
||||||
|
} else {
|
||||||
|
$services[] = EloquentBuilderPaginatorService::class;
|
||||||
|
}
|
||||||
|
|
||||||
return $services;
|
return $services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,13 @@ namespace App\Repositories;
|
|||||||
use App\Character;
|
use App\Character;
|
||||||
use App\Contracts\CharacterRepository;
|
use App\Contracts\CharacterRepository;
|
||||||
use App\Contracts\Repository;
|
use App\Contracts\Repository;
|
||||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
use Illuminate\Contracts\Database\Query\Builder as EloquentBuilder;
|
||||||
use Laravel\Scout\Builder as ScoutBuilder;
|
use Laravel\Scout\Builder as ScoutBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements Repository<Character>
|
* @implements Repository<Character>
|
||||||
*/
|
*/
|
||||||
class DefaultCharacterRepository extends DatabaseRepository implements CharacterRepository
|
final class DefaultCharacterRepository extends DatabaseRepository implements CharacterRepository
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,7 @@ use App\Contracts\Repository;
|
|||||||
/**
|
/**
|
||||||
* @implements Repository<Club>
|
* @implements Repository<Club>
|
||||||
*/
|
*/
|
||||||
class DefaultClubRepository extends DatabaseRepository implements ClubRepository
|
final class DefaultClubRepository extends DatabaseRepository implements ClubRepository
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,7 @@ use App\Magazine;
|
|||||||
/**
|
/**
|
||||||
* @implements Repository<Magazine>
|
* @implements Repository<Magazine>
|
||||||
*/
|
*/
|
||||||
class DefaultMagazineRepository extends DatabaseRepository implements MagazineRepository
|
final class DefaultMagazineRepository extends DatabaseRepository implements MagazineRepository
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,7 @@ use App\Manga;
|
|||||||
use Illuminate\Contracts\Database\Query\Builder as EloquentBuilder;
|
use Illuminate\Contracts\Database\Query\Builder as EloquentBuilder;
|
||||||
use Laravel\Scout\Builder as ScoutBuilder;
|
use Laravel\Scout\Builder as ScoutBuilder;
|
||||||
|
|
||||||
class DefaultMangaRepository extends DatabaseRepository implements MangaRepository
|
final class DefaultMangaRepository extends DatabaseRepository implements MangaRepository
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,7 @@ namespace App\Repositories;
|
|||||||
use App\Contracts\PeopleRepository;
|
use App\Contracts\PeopleRepository;
|
||||||
use App\Contracts\Repository;
|
use App\Contracts\Repository;
|
||||||
use App\Person;
|
use App\Person;
|
||||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
use Illuminate\Contracts\Database\Query\Builder as EloquentBuilder;
|
||||||
use Laravel\Scout\Builder as ScoutBuilder;
|
use Laravel\Scout\Builder as ScoutBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,7 @@ use App\Producers;
|
|||||||
/**
|
/**
|
||||||
* @implements Repository<Producers>
|
* @implements Repository<Producers>
|
||||||
*/
|
*/
|
||||||
class DefaultProducerRepository extends DatabaseRepository implements ProducerRepository
|
final class DefaultProducerRepository extends DatabaseRepository implements ProducerRepository
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,7 @@ use App\Profile;
|
|||||||
/**
|
/**
|
||||||
* @implements Repository<Profile>
|
* @implements Repository<Profile>
|
||||||
*/
|
*/
|
||||||
class DefaultUserRepository extends DatabaseRepository implements UserRepository
|
final class DefaultUserRepository extends DatabaseRepository implements UserRepository
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Concerns\ScraperCacheTtl;
|
|
||||||
use App\Contracts\CachedScraperService;
|
use App\Contracts\CachedScraperService;
|
||||||
use App\Contracts\Repository;
|
use App\Contracts\Repository;
|
||||||
use App\Http\HttpHelper;
|
use App\Http\HttpHelper;
|
||||||
@ -19,8 +18,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
*/
|
*/
|
||||||
final class DefaultCachedScraperService implements CachedScraperService
|
final class DefaultCachedScraperService implements CachedScraperService
|
||||||
{
|
{
|
||||||
use ScraperCacheTtl;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly Repository $repository,
|
private readonly Repository $repository,
|
||||||
private readonly MalClient $jikan,
|
private readonly MalClient $jikan,
|
||||||
@ -133,7 +130,7 @@ final class DefaultCachedScraperService implements CachedScraperService
|
|||||||
$this->repository->queryByMalId($id)->update($response->toArray());
|
$this->repository->queryByMalId($id)->update($response->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CachedData(collect($this->repository->getAllByMalId($id)));
|
return CachedData::from(collect($this->repository->getAllByMalId($id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateCacheByKey(string $cacheKey, CachedData $results, array $scraperResponse): CachedData
|
private function updateCacheByKey(string $cacheKey, CachedData $results, array $scraperResponse): CachedData
|
||||||
@ -149,7 +146,7 @@ final class DefaultCachedScraperService implements CachedScraperService
|
|||||||
$this->getQueryableByCacheKey($cacheKey)->update($response->toArray());
|
$this->getQueryableByCacheKey($cacheKey)->update($response->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CachedData($this->getByCacheKey($cacheKey));
|
return CachedData::from($this->getByCacheKey($cacheKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function prepareScraperResponse(string $cacheKey, bool $resultsEmpty, array $scraperResponse): CachedData
|
private function prepareScraperResponse(string $cacheKey, bool $resultsEmpty, array $scraperResponse): CachedData
|
||||||
@ -166,7 +163,7 @@ final class DefaultCachedScraperService implements CachedScraperService
|
|||||||
$meta['modifiedAt'] = new UTCDateTime();
|
$meta['modifiedAt'] = new UTCDateTime();
|
||||||
|
|
||||||
// join meta data with response
|
// join meta data with response
|
||||||
return new CachedData(collect($meta + $scraperResponse));
|
return CachedData::from(collect($meta + $scraperResponse));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getByCacheKey(string $cacheKey): Collection
|
private function getByCacheKey(string $cacheKey): Collection
|
||||||
@ -179,7 +176,7 @@ final class DefaultCachedScraperService implements CachedScraperService
|
|||||||
return $this->repository->where("request_hash", $cacheKey);
|
return $this->repository->where("request_hash", $cacheKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function serializeScraperResult(array $data): array
|
private function serializeScraperResult(mixed $data): array
|
||||||
{
|
{
|
||||||
return $this->serializer->toArray($data);
|
return $this->serializer->toArray($data);
|
||||||
}
|
}
|
||||||
|
22
app/Support/CacheOptions.php
Normal file
22
app/Support/CacheOptions.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Support;
|
||||||
|
|
||||||
|
final class CacheOptions
|
||||||
|
{
|
||||||
|
private ?int $ttl = null;
|
||||||
|
|
||||||
|
public function __construct(private readonly JikanConfig $jikanConfig)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ttl(): int
|
||||||
|
{
|
||||||
|
return $this->ttl ?? $this->jikanConfig->defaultCacheExpire();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTtl(?int $ttl): void
|
||||||
|
{
|
||||||
|
$this->ttl = $ttl;
|
||||||
|
}
|
||||||
|
}
|
@ -5,20 +5,23 @@ namespace App\Support;
|
|||||||
use App\Concerns\ScraperCacheTtl;
|
use App\Concerns\ScraperCacheTtl;
|
||||||
use App\JikanApiModel;
|
use App\JikanApiModel;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Env;
|
||||||
|
|
||||||
final class CachedData
|
final class CachedData
|
||||||
{
|
{
|
||||||
use ScraperCacheTtl;
|
private int $cacheTimeToLive;
|
||||||
|
|
||||||
public function __construct(
|
private function __construct(
|
||||||
private readonly Collection $scraperResult
|
private readonly Collection $scraperResult,
|
||||||
|
int $cacheTtl
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
$this->cacheTimeToLive = $cacheTtl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function from(Collection $scraperResult): self
|
public static function from(Collection $scraperResult): self
|
||||||
{
|
{
|
||||||
return new self($scraperResult);
|
return new self($scraperResult, app(CacheOptions::class)->ttl());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function collect(): Collection
|
public function collect(): Collection
|
||||||
@ -62,10 +65,15 @@ final class CachedData
|
|||||||
public function expiry(): int
|
public function expiry(): int
|
||||||
{
|
{
|
||||||
$modifiedAt = $this->lastModified();
|
$modifiedAt = $this->lastModified();
|
||||||
$ttl = $this->cacheTtl();
|
$ttl = $this->cacheTimeToLive;
|
||||||
return $modifiedAt !== null ? $ttl + $modifiedAt : $ttl;
|
return $modifiedAt !== null ? $ttl + $modifiedAt : $ttl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function cacheTtl(): int
|
||||||
|
{
|
||||||
|
return $this->cacheTimeToLive;
|
||||||
|
}
|
||||||
|
|
||||||
public function lastModified(): ?int
|
public function lastModified(): ?int
|
||||||
{
|
{
|
||||||
if ($this->scraperResult->isEmpty()) {
|
if ($this->scraperResult->isEmpty()) {
|
||||||
|
35
app/Support/JikanConfig.php
Normal file
35
app/Support/JikanConfig.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Support;
|
||||||
|
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jikan behavior config
|
||||||
|
*/
|
||||||
|
final class JikanConfig
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array<string, int> $perEndpointCacheTtl
|
||||||
|
*/
|
||||||
|
private array $perEndpointCacheTtl;
|
||||||
|
|
||||||
|
private int $defaultCacheExpire;
|
||||||
|
|
||||||
|
public function __construct(array $config)
|
||||||
|
{
|
||||||
|
$config = collect($config);
|
||||||
|
$this->perEndpointCacheTtl = $config->get("per_endpoint_cache_ttl", []);
|
||||||
|
$this->defaultCacheExpire = $config->get("default_cache_expire", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cacheTtlForEndpoint(string $endpoint): ?int
|
||||||
|
{
|
||||||
|
return collect($this->perEndpointCacheTtl)->get($endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defaultCacheExpire(): int
|
||||||
|
{
|
||||||
|
return $this->defaultCacheExpire;
|
||||||
|
}
|
||||||
|
}
|
@ -6,8 +6,8 @@ use Illuminate\Contracts\Database\Query\Builder;
|
|||||||
|
|
||||||
class RepositoryQueryBase
|
class RepositoryQueryBase
|
||||||
{
|
{
|
||||||
private ?Builder $queryableBuilder;
|
private ?Builder $queryableBuilder = null;
|
||||||
private ?ScoutBuilder $searchableBuilder;
|
private ?ScoutBuilder $searchableBuilder = null;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly \Closure $getQueryable,
|
private readonly \Closure $getQueryable,
|
||||||
|
@ -41,7 +41,6 @@ $app->instance('path.config', app()->basePath() . DIRECTORY_SEPARATOR . 'config'
|
|||||||
$app->instance('path.storage', app()->basePath() . DIRECTORY_SEPARATOR . 'storage');
|
$app->instance('path.storage', app()->basePath() . DIRECTORY_SEPARATOR . 'storage');
|
||||||
|
|
||||||
$app->withEloquent();
|
$app->withEloquent();
|
||||||
|
|
||||||
$app->configure('swagger-lume');
|
$app->configure('swagger-lume');
|
||||||
$app->configure('scout');
|
$app->configure('scout');
|
||||||
|
|
||||||
@ -88,6 +87,7 @@ $app->middleware($globalMiddleware);
|
|||||||
$app->routeMiddleware([
|
$app->routeMiddleware([
|
||||||
'microcaching' => \App\Http\Middleware\MicroCaching::class,
|
'microcaching' => \App\Http\Middleware\MicroCaching::class,
|
||||||
'source-health-monitor' => SourceHeartbeatMonitor::class,
|
'source-health-monitor' => SourceHeartbeatMonitor::class,
|
||||||
|
'cache-ttl' => \App\Http\Middleware\EndpointCacheTtlMiddleware::class
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -109,6 +109,7 @@ $app->configure('controller-to-table-mapping');
|
|||||||
$app->configure('controller');
|
$app->configure('controller');
|
||||||
$app->configure('roadrunner');
|
$app->configure('roadrunner');
|
||||||
$app->configure('data');
|
$app->configure('data');
|
||||||
|
$app->configure('jikan');
|
||||||
|
|
||||||
$app->register(\pushrbx\LumenRoadRunner\ServiceProvider::class);
|
$app->register(\pushrbx\LumenRoadRunner\ServiceProvider::class);
|
||||||
$app->register(\SwaggerLume\ServiceProvider::class);
|
$app->register(\SwaggerLume\ServiceProvider::class);
|
||||||
@ -169,6 +170,7 @@ if (env("SCOUT_DRIVER") === "Matchish\ScoutElasticSearch\Engines\ElasticSearchEn
|
|||||||
$commonMiddleware = [
|
$commonMiddleware = [
|
||||||
'source-health-monitor',
|
'source-health-monitor',
|
||||||
'microcaching',
|
'microcaching',
|
||||||
|
'cache-ttl'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
143
config/jikan.php
Normal file
143
config/jikan.php
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'default_cache_expire' => env('CACHE_DEFAULT_EXPIRE', 86400),
|
||||||
|
'per_endpoint_cache_ttl' => [
|
||||||
|
/**
|
||||||
|
* Anime
|
||||||
|
*/
|
||||||
|
'AnimeController@main' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@characters_staff' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@characters' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@staff' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@episodes' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@episode' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@news' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@forum' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@videos' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@videosEpisodes' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@pictures' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@stats' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@moreInfo' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@recommendations' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@userupdates' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'AnimeController@reviews' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manga
|
||||||
|
*/
|
||||||
|
'MangaController@main' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'MangaController@characters' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'MangaController@news' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'MangaController@forum' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'MangaController@pictures' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'MangaController@stats' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'MangaController@moreInfo' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'MangaController@recommendations' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'MangaController@userupdates' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'MangaController@reviews' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Characters
|
||||||
|
*/
|
||||||
|
'CharacterController@main' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'CharacterController@anime' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'CharacterController@manga' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'CharacterController@voices' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'CharacterController@pictures' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Person
|
||||||
|
*/
|
||||||
|
'PersonController@main' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'PersonController@anime' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'PersonController@manga' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'PersonController@seiyuu' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'PersonController@pictures' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Season
|
||||||
|
*/
|
||||||
|
'SeasonController@archive' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'SeasonController@later' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'SeasonController@main' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule
|
||||||
|
*/
|
||||||
|
'ScheduleController@main' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Producers
|
||||||
|
*/
|
||||||
|
'ProducerController@main' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magazines
|
||||||
|
*/
|
||||||
|
'MagazineController@main' => env('CACHE_MAGAZINE_EXPIRE'),
|
||||||
|
'MagazineController@resource' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Users
|
||||||
|
*/
|
||||||
|
'UserController@recentlyOnline' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'UserController@profile' => env('CACHE_USER_EXPIRE'),
|
||||||
|
'UserController@statistics' => env('CACHE_USER_EXPIRE'),
|
||||||
|
'UserController@favorites' => env('CACHE_USER_EXPIRE'),
|
||||||
|
'UserController@about' => env('CACHE_USER_EXPIRE'),
|
||||||
|
'UserController@history' => env('CACHE_USER_EXPIRE'),
|
||||||
|
'UserController@friends' => env('CACHE_USER_EXPIRE'),
|
||||||
|
'UserController@recommendations' => env('CACHE_USER_EXPIRE'),
|
||||||
|
'UserController@reviews' => env('CACHE_USER_EXPIRE'),
|
||||||
|
'UserController@clubs' => env('CACHE_USER_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User Lists
|
||||||
|
*/
|
||||||
|
'UserController@animelist' => env('CACHE_USERLIST_EXPIRE'),
|
||||||
|
'UserController@mangalist' => env('CACHE_USERLIST_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Genre
|
||||||
|
*/
|
||||||
|
'GenreController@mainAnime' => env('CACHE_GENRE_EXPIRE'),
|
||||||
|
'GenreController@mainManga' => env('CACHE_GENRE_EXPIRE'),
|
||||||
|
'GenreController@anime' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'GenreController@manga' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Top
|
||||||
|
*/
|
||||||
|
'TopController@anime' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'TopController@manga' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'TopController@characters' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'TopController@people' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'TopController@reviews' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search
|
||||||
|
*/
|
||||||
|
'SearchController@anime' => env('CACHE_SEARCH_EXPIRE'),
|
||||||
|
'SearchController@manga' => env('CACHE_SEARCH_EXPIRE'),
|
||||||
|
'SearchController@character' => env('CACHE_SEARCH_EXPIRE'),
|
||||||
|
'SearchController@people' => env('CACHE_SEARCH_EXPIRE'),
|
||||||
|
'SearchController@users' => env('CACHE_SEARCH_EXPIRE'),
|
||||||
|
'SearchController@userById' => env('CACHE_SEARCH_EXPIRE'),
|
||||||
|
'SearchController@producers' => env('CACHE_SEARCH_EXPIRE'),
|
||||||
|
|
||||||
|
'ClubController@main' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'ClubController@members' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
'ReviewsController@anime' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'ReviewsController@manga' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
'RecommendationsController@anime' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'RecommendationsController@manga' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
|
||||||
|
'WatchController@recentEpisodes' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'WatchController@popularEpisodes' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'WatchController@recentPromos' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
'WatchController@popularPromos' => env('CACHE_DEFAULT_EXPIRE'),
|
||||||
|
]
|
||||||
|
];
|
@ -15,7 +15,7 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
|
|||||||
{
|
{
|
||||||
use JikanDataGenerator;
|
use JikanDataGenerator;
|
||||||
|
|
||||||
protected ?MediaModelFactoryDescriptor $descriptor;
|
protected ?MediaModelFactoryDescriptor $descriptor = null;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
MediaModelFactoryDescriptor $descriptor,
|
MediaModelFactoryDescriptor $descriptor,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user