wip - mediator refactor

This commit is contained in:
pushrbx 2023-01-20 20:55:43 +00:00
parent 69d66378be
commit c564de979d
62 changed files with 1332 additions and 1114 deletions

View File

@ -3,7 +3,7 @@
namespace App\Dto;
use App\Casts\EnumCast;
use App\Enums\AnimeReviewsSortEnum;
use App\Enums\MediaReviewsSortEnum;
use Illuminate\Http\JsonResponse;
use Spatie\Enum\Laravel\Rules\EnumRule;
use Spatie\LaravelData\Attributes\Validation\BooleanType;
@ -19,8 +19,8 @@ final class AnimeReviewsLookupCommand extends LookupDataCommand
#[Numeric]
public int|Optional $page;
#[WithCast(EnumCast::class, AnimeReviewsSortEnum::class)]
public AnimeReviewsSortEnum|Optional $sort;
#[WithCast(EnumCast::class, MediaReviewsSortEnum::class)]
public MediaReviewsSortEnum|Optional $sort;
#[BooleanType]
public bool|Optional $spoilers;
@ -31,7 +31,7 @@ final class AnimeReviewsLookupCommand extends LookupDataCommand
public static function rules(): array
{
return [
"sort" => [new EnumRule(AnimeReviewsSortEnum::class)]
"sort" => [new EnumRule(MediaReviewsSortEnum::class)]
];
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class CharacterAnimeLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class CharacterFullLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class CharacterLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class CharacterMangaLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class CharacterPicturesLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class CharacterVoicesLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class ClubLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,16 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
use Spatie\LaravelData\Attributes\Validation\Numeric;
use Spatie\LaravelData\Optional;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class ClubMembersLookupCommand extends LookupDataCommand
{
#[Numeric]
public int|Optional $page;
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class ClubRelationLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class ClubStaffLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaCharactersLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaExternalLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,27 @@
<?php
namespace App\Dto;
use App\Casts\EnumCast;
use App\Enums\MangaForumFilterEnum;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Optional;
use Spatie\Enum\Laravel\Rules\EnumRule;
use Spatie\LaravelData\Attributes\WithCast;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaForumLookupCommand extends LookupDataCommand
{
#[WithCast(EnumCast::class, MangaForumFilterEnum::class)]
public MangaForumFilterEnum|Optional $filter;
public static function rules(): array
{
return [
"filter" => [new EnumRule(MangaForumFilterEnum::class)]
];
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaFullLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaMoreInfoLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
use Spatie\LaravelData\Attributes\Validation\Numeric;
use Spatie\LaravelData\Optional;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaNewsLookupCommand extends LookupDataCommand
{
#[Numeric]
public int|Optional $page;
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaPicturesLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaRecommendationsLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaRelationsLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Dto;
use App\Casts\EnumCast;
use App\Enums\MediaReviewsSortEnum;
use Illuminate\Http\JsonResponse;
use Spatie\Enum\Laravel\Rules\EnumRule;
use Spatie\LaravelData\Attributes\Validation\BooleanType;
use Spatie\LaravelData\Attributes\Validation\Numeric;
use Spatie\LaravelData\Attributes\WithCast;
use Spatie\LaravelData\Optional;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaReviewsLookupCommand extends LookupDataCommand
{
#[Numeric]
public int|Optional $page;
#[WithCast(EnumCast::class, MediaReviewsSortEnum::class)]
public MediaReviewsSortEnum|Optional $sort;
#[BooleanType]
public bool|Optional $spoilers;
#[BooleanType]
public bool|Optional $preliminary;
public static function rules(): array
{
return [
"sort" => [new EnumRule(MediaReviewsSortEnum::class)]
];
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaStatsLookupCommand extends LookupDataCommand
{
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Dto;
use Illuminate\Http\JsonResponse;
use Spatie\LaravelData\Attributes\Validation\Numeric;
use Spatie\LaravelData\Optional;
/**
* @extends LookupDataCommand<JsonResponse>
*/
final class MangaUserUpdatesLookupCommand extends LookupDataCommand
{
#[Numeric]
public int|Optional $page;
}

View File

@ -0,0 +1,15 @@
<?php
namespace App\Enums;
use Spatie\Enum\Laravel\Enum;
/**
* @method static self all()
* @method static self chapters()
* @method static self other()
*/
final class MangaForumFilterEnum extends Enum
{
}

View File

@ -10,7 +10,7 @@ use Spatie\Enum\Laravel\Enum;
* @method static self newest()
* @method static self oldest()
*/
final class AnimeReviewsSortEnum extends Enum
final class MediaReviewsSortEnum extends Enum
{
protected static function labels(): array
{

View File

@ -12,7 +12,7 @@ use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<AnimeFullLookupCommand, JsonResponse>
*/
final class QueryFullAnimeHandler extends ItemLookupHandler
final class AnimeFullLookupHandler extends ItemLookupHandler
{
public function requestClass(): string
{

View File

@ -11,7 +11,7 @@ use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<AnimeLookupCommand, JsonResponse>
*/
final class QueryAnimeHandler extends ItemLookupHandler
final class AnimeLookupHandler extends ItemLookupHandler
{
protected function resource(Collection $results): JsonResource
{

View File

@ -3,9 +3,12 @@
namespace App\Features;
use App\Dto\AnimeReviewsLookupCommand;
use App\Enums\AnimeReviewsSortEnum;
use App\Enums\MediaReviewsSortEnum;
use App\Features\Concerns\ResolvesMediaReviewParams;
use App\Http\Resources\V4\ReviewsResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Anime\AnimeReviewsRequest;
@ -15,6 +18,8 @@ use Jikan\Request\Anime\AnimeReviewsRequest;
*/
final class AnimeReviewsLookupHandler extends RequestHandlerWithScraperCache
{
use ResolvesMediaReviewParams;
/**
* @inheritDoc
*/
@ -23,12 +28,16 @@ final class AnimeReviewsLookupHandler extends RequestHandlerWithScraperCache
return AnimeReviewsLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new ReviewsResource($results->first());
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$id = $requestParams->get("id");
$sort = $requestParams->get("sort", AnimeReviewsSortEnum::mostVoted()->value);
$spoilers = $requestParams->get("spoilers", false);
$preliminary = $requestParams->get("preliminary", false);
$reviewRequestParams = $this->getReviewRequestParams($requestParams);
// import array members as variables into the current scope's symbol table
extract($reviewRequestParams);
return $this->scraperService->findList(
$requestFingerPrint,

View File

@ -0,0 +1,31 @@
<?php
namespace App\Features;
use App\Dto\CharacterAnimeLookupCommand;
use App\Http\Resources\V4\CharacterAnimeCollection;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<CharacterAnimeLookupCommand, JsonResponse>
*/
final class CharacterAnimeLookupHandler extends ItemLookupHandler
{
protected function resource(Collection $results): JsonResource
{
/** @noinspection PhpUndefinedMethodInspection */
return new CharacterAnimeCollection(
$results->offsetGetFirst("animeography")
);
}
/**
* @inheritDoc
*/
public function requestClass(): string
{
return CharacterAnimeLookupCommand::class;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Features;
use App\Dto\CharacterFullLookupCommand;
use App\Http\Resources\V4\CharacterFullResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<CharacterFullLookupCommand, JsonResponse>
*/
final class CharacterFullLookupHandler extends ItemLookupHandler
{
protected function resource(Collection $results): JsonResource
{
return new CharacterFullResource($results->first());
}
/**
* @inheritDoc
*/
public function requestClass(): string
{
return CharacterFullLookupCommand::class;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Features;
use App\Dto\CharacterLookupCommand;
use App\Http\Resources\V4\CharacterResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<CharacterLookupCommand, JsonResponse>
*/
final class CharacterLookupHandler extends ItemLookupHandler
{
protected function resource(Collection $results): JsonResource
{
return new CharacterResource($results->first());
}
/**
* @inheritDoc
*/
public function requestClass(): string
{
return CharacterLookupCommand::class;
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Features;
use App\Dto\CharacterMangaLookupCommand;
use App\Http\Resources\V4\CharacterMangaCollection;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<CharacterMangaLookupCommand, JsonResponse>
*/
final class CharacterMangaLookupHandler extends ItemLookupHandler
{
protected function resource(Collection $results): JsonResource
{
/** @noinspection PhpUndefinedMethodInspection */
return new CharacterMangaCollection(
$results->offsetGetFirst("mangaography")
);
}
/**
* @inheritDoc
*/
public function requestClass(): string
{
return CharacterMangaLookupCommand::class;
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace App\Features;
use App\Dto\CharacterPicturesLookupCommand;
use App\Http\Resources\V4\PicturesResource;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Character\CharacterPicturesRequest;
/**
* @extends RequestHandlerWithScraperCache<CharacterPicturesLookupCommand, JsonResponse>
*/
final class CharacterPicturesLookupHandler extends RequestHandlerWithScraperCache
{
protected function resource(Collection $results): JsonResource
{
return new PicturesResource($results->first());
}
/**
* @inheritDoc
*/
public function requestClass(): string
{
return CharacterPicturesLookupCommand::class;
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$id = $requestParams->get("id");
return $this->scraperService->findList(
$requestFingerPrint,
fn (MalClient $jikan, ?int $page = null) => [
"pictures" => $jikan->getCharacterPictures(new CharacterPicturesRequest($id))
]
);
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Features;
use App\Dto\CharacterVoicesLookupCommand;
use App\Http\Resources\V4\CharacterSeiyuuCollection;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<CharacterVoicesLookupCommand, JsonResponse>
*/
final class CharacterVoicesLookupHandler extends ItemLookupHandler
{
protected function resource(Collection $results): JsonResource
{
/** @noinspection PhpUndefinedMethodInspection */
return new CharacterSeiyuuCollection(
$results->offsetGetFirst("voice_actors")
);
}
/**
* @inheritDoc
*/
public function requestClass(): string
{
return CharacterVoicesLookupCommand::class;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Features;
use App\Dto\ClubLookupCommand;
use App\Http\Resources\V4\ClubResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<ClubLookupCommand, JsonResponse>
*/
final class ClubLookupHandler extends ItemLookupHandler
{
protected function resource(Collection $results): JsonResource
{
return new ClubResource($results->first());
}
/**
* @inheritDoc
*/
public function requestClass(): string
{
return ClubLookupCommand::class;
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace App\Features;
use App\Dto\ClubMembersLookupCommand;
use App\Support\CachedData;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Club\UserListRequest;
/**
* @extends RequestHandlerWithScraperCache<ClubMembersLookupCommand, JsonResponse>
*/
final class ClubMembersLookupHandler extends RequestHandlerWithScraperCache
{
/**
* @inheritDoc
*/
public function requestClass(): string
{
return ClubMembersLookupCommand::class;
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$id = $requestParams->get("id");
return $this->scraperService->findList(
$requestFingerPrint,
fn(MalClient $jikan, ?int $page = null) => $jikan->getClubUsers(new UserListRequest($id, $page)),
$requestParams->get("page", 1)
);
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Features;
use App\Dto\ClubRelationLookupCommand;
use App\Http\Resources\V4\ClubRelationsResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<ClubRelationLookupCommand, JsonResponse>
*/
final class ClubRelationsLookupHandler extends ItemLookupHandler
{
protected function resource(Collection $results): JsonResource
{
return new ClubRelationsResource($results->first());
}
/**
* @inheritDoc
*/
public function requestClass(): string
{
return ClubRelationLookupCommand::class;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Features;
use App\Dto\ClubStaffLookupCommand;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use App\Http\Resources\V4\ClubStaffResource;
/**
* @extends ItemLookupHandler<ClubStaffLookupCommand, JsonResponse>
*/
final class ClubStaffLookupHandler extends ItemLookupHandler
{
protected function resource(Collection $results): JsonResource
{
return new ClubStaffResource($results->first());
}
/**
* @inheritDoc
*/
public function requestClass(): string
{
return ClubStaffLookupCommand::class;
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Features\Concerns;
use App\Enums\MediaReviewsSortEnum;
use Illuminate\Support\Collection;
trait ResolvesMediaReviewParams
{
protected function getReviewRequestParams(Collection $requestParams): array
{
$id = $requestParams->get("id");
$sort = $requestParams->get("sort", MediaReviewsSortEnum::mostVoted()->value);
$spoilers = $requestParams->get("spoilers", false);
$preliminary = $requestParams->get("preliminary", false);
return compact($id, $sort, $spoilers, $preliminary);
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace App\Features;
use App\Dto\MangaCharactersLookupCommand;
use App\Http\Resources\V4\MangaCharactersResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use App\Support\CachedData;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Manga\MangaCharactersRequest;
/**
* @extends RequestHandlerWithScraperCache<MangaCharactersLookupCommand, JsonResponse>
*/
final class MangaCharactersLookupHandler extends RequestHandlerWithScraperCache
{
public function requestClass(): string
{
return MangaCharactersLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new MangaCharactersResource($results->first());
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$id = $requestParams->get("id");
return $this->scraperService->findList(
$requestFingerPrint,
fn(MalClient $jikan, ?int $page = null) => $jikan->getMangaCharacters(new MangaCharactersRequest($id))
);
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Features;
use App\Dto\MangaExternalLookupCommand;
use App\Http\Resources\V4\ExternalLinksResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<MangaExternalLookupCommand, JsonResponse>
*/
final class MangaExternalLookupHandler extends ItemLookupHandler
{
public function requestClass(): string
{
return MangaExternalLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new ExternalLinksResource($results->first());
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace App\Features;
use App\Dto\MangaForumLookupCommand;
use App\Http\Resources\V4\ForumResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use App\Support\CachedData;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Manga\MangaForumRequest;
/**
* @extends RequestHandlerWithScraperCache<MangaForumLookupCommand, JsonResponse>
*/
final class MangaForumLookupHandler extends RequestHandlerWithScraperCache
{
public function requestClass(): string
{
return MangaForumLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new ForumResource($results->first());
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$id = $requestParams->get("id");
$filter = $requestParams->get("filter");
return $this->scraperService->findList(
$requestFingerPrint,
fn(MalClient $jikan, ?int $page = null) => collect(
["topics" => $jikan->getMangaForum(new MangaForumRequest($id, $filter))]
)
);
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Features;
use App\Dto\MangaFullLookupCommand;
use App\Http\Resources\V4\MangaFullResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<MangaFullLookupCommand, JsonResponse>
*/
final class MangaFullLookupHandler extends ItemLookupHandler
{
public function requestClass(): string
{
return MangaFullLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new MangaFullResource($results->first());
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Features;
use App\Dto\MangaLookupCommand;
use App\Http\Resources\V4\MangaResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<MangaLookupCommand, JsonResponse>
*/
final class MangaLookupHandler extends ItemLookupHandler
{
public function requestClass(): string
{
return MangaLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new MangaResource($results->first());
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Features;
use App\Dto\MangaMoreInfoLookupCommand;
use App\Http\Resources\V4\MoreInfoResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use App\Support\CachedData;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Manga\MangaMoreInfoRequest;
/**
* @extends RequestHandlerWithScraperCache<MangaMoreInfoLookupCommand, JsonResponse>
*/
final class MangaMoreInfoLookupHandler extends RequestHandlerWithScraperCache
{
public function requestClass(): string
{
return MangaMoreInfoLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new MoreInfoResource($results->first());
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$id = $requestParams->get("id");
return $this->scraperService->findList(
$requestFingerPrint,
fn(MalClient $jikan, ?int $page = null) => collect(
["moreinfo" => $jikan->getMangaMoreInfo(new MangaMoreInfoRequest($id))]
)
);
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Features;
use App\Dto\MangaNewsLookupCommand;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
use App\Support\CachedData;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Manga\MangaNewsRequest;
/**
* @extends RequestHandlerWithScraperCache<MangaNewsLookupCommand, JsonResponse>
*/
final class MangaNewsLookupHandler extends RequestHandlerWithScraperCache
{
public function requestClass(): string
{
return MangaNewsLookupCommand::class;
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$id = $requestParams->get("id");
return $this->scraperService->findList(
$requestFingerPrint,
fn(MalClient $jikan, ?int $page = null) => $jikan->getNewsList(new MangaNewsRequest($id, $page)),
$requestParams->get("page", 1)
);
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Features;
use App\Dto\MangaPicturesLookupCommand;
use App\Http\Resources\V4\PicturesResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use App\Support\CachedData;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Manga\MangaPicturesRequest;
/**
* @extends RequestHandlerWithScraperCache<MangaPicturesLookupCommand, JsonResponse>
*/
final class MangaPicturesLookupHandler extends RequestHandlerWithScraperCache
{
public function requestClass(): string
{
return MangaPicturesLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new PicturesResource($results->first());
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$id = $requestParams->get("id");
return $this->scraperService->findList(
$requestFingerPrint,
fn(MalClient $jikan, ?int $page = null) => collect(
["pictures" => $jikan->getMangaPictures(new MangaPicturesRequest($id))]
)
);
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Features;
use App\Dto\MangaRecommendationsLookupCommand;
use App\Http\Resources\V4\RecommendationsResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use App\Support\CachedData;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Manga\MangaRecommendationsRequest;
/**
* @extends RequestHandlerWithScraperCache<MangaRecommendationsLookupCommand, JsonResponse>
*/
final class MangaRecommendationsLookupHandler extends RequestHandlerWithScraperCache
{
public function requestClass(): string
{
return MangaRecommendationsLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new RecommendationsResource($results->first());
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$id = $requestParams->get("id");
return $this->scraperService->findList(
$requestFingerPrint,
fn(MalClient $jikan, ?int $page = null) => collect(
["recommendations" => $jikan->getMangaRecommendations(new MangaRecommendationsRequest($id))]
)
);
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Features;
use App\Dto\MangaRelationsLookupCommand;
use App\Http\Resources\V4\MangaRelationsResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
/**
* @extends ItemLookupHandler<MangaRelationsLookupCommand, JsonResponse>
*/
final class MangaRelationsLookupHandler extends ItemLookupHandler
{
public function requestClass(): string
{
return MangaRelationsLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new MangaRelationsResource($results->first());
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace App\Features;
use App\Dto\MangaReviewsLookupCommand;
use App\Features\Concerns\ResolvesMediaReviewParams;
use App\Http\Resources\V4\ReviewsResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use App\Support\CachedData;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Manga\MangaReviewsRequest;
/**
* @extends RequestHandlerWithScraperCache<MangaReviewsLookupCommand, JsonResponse>
*/
final class MangaReviewsLookupHandler extends RequestHandlerWithScraperCache
{
use ResolvesMediaReviewParams;
public function requestClass(): string
{
return MangaReviewsLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new ReviewsResource($results->first());
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$reviewRequestParams = $this->getReviewRequestParams($requestParams);
// import array members as variables into the current scope's symbol table
extract($reviewRequestParams);
return $this->scraperService->findList(
$requestFingerPrint,
fn(MalClient $jikan, ?int $page = null) => $jikan->getMangaReviews(new MangaReviewsRequest(
$id, $page, $sort, $spoilers, $preliminary
)),
$requestParams->get("page", 1)
);
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace App\Features;
use App\Dto\MangaStatsLookupCommand;
use App\Http\Resources\V4\MangaStatisticsResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use App\Support\CachedData;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Manga\MangaStatsRequest;
/**
* @extends RequestHandlerWithScraperCache<MangaStatsLookupCommand, JsonResponse>
*/
final class MangaStatsLookupHandler extends RequestHandlerWithScraperCache
{
public function requestClass(): string
{
return MangaStatsLookupCommand::class;
}
protected function resource(Collection $results): JsonResource
{
return new MangaStatisticsResource($results->first());
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$id = $requestParams->get("id");
return $this->scraperService->findList(
$requestFingerPrint,
fn(MalClient $jikan, ?int $page = null) => $jikan->getMangaStats(new MangaStatsRequest($id))
);
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Features;
use App\Dto\MangaUserUpdatesLookupCommand;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
use App\Support\CachedData;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Manga\MangaRecentlyUpdatedByUsersRequest;
/**
* @extends RequestHandlerWithScraperCache<MangaUserUpdatesLookupCommand, JsonResponse>
*/
final class MangaUserUpdatesLookupHandler extends RequestHandlerWithScraperCache
{
public function requestClass(): string
{
return MangaUserUpdatesLookupCommand::class;
}
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
{
$id = $requestParams->get("id");
return $this->scraperService->findList(
$requestFingerPrint,
fn(MalClient $jikan, ?int $page = null) => $jikan->getMangaRecentlyUpdatedByUsers(new MangaRecentlyUpdatedByUsersRequest($id, $page)),
$requestParams->get("page", 1)
);
}
}

View File

@ -4,6 +4,12 @@ namespace App\Http\Controllers\V4DB;
use App\Anime;
use App\Character;
use App\Dto\CharacterAnimeLookupCommand;
use App\Dto\CharacterFullLookupCommand;
use App\Dto\CharacterLookupCommand;
use App\Dto\CharacterMangaLookupCommand;
use App\Dto\CharacterPicturesLookupCommand;
use App\Dto\CharacterVoicesLookupCommand;
use App\Http\HttpHelper;
use App\Http\HttpResponse;
use App\Http\Resources\V4\CharacterAnimeCollection;
@ -53,59 +59,8 @@ class CharacterController extends Controller
*/
public function full(Request $request, int $id)
{
$results = Character::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Character::scrape($id);
if (HttpHelper::hasError($response)) {
return HttpResponse::notFound($request);
}
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Character::create($response);
}
if ($this->isExpired($request, $results)) {
Character::query()
->where('mal_id', $id)
->update($response);
}
$results = Character::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new \App\Http\Resources\V4\CharacterFullResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = CharacterFullLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -113,7 +68,7 @@ class CharacterController extends Controller
* path="/characters/{id}",
* operationId="getCharacterById",
* tags={"characters"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
@ -139,59 +94,8 @@ class CharacterController extends Controller
*/
public function main(Request $request, int $id)
{
$results = Character::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Character::scrape($id);
if (HttpHelper::hasError($response)) {
return HttpResponse::notFound($request);
}
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Character::create($response);
}
if ($this->isExpired($request, $results)) {
Character::query()
->where('mal_id', $id)
->update($response);
}
$results = Character::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new \App\Http\Resources\V4\CharacterResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = CharacterLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -220,56 +124,8 @@ class CharacterController extends Controller
*/
public function anime(Request $request, int $id)
{
$results = Character::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Character::scrape($id);
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Character::create($response);
}
if ($this->isExpired($request, $results)) {
Character::query()
->where('mal_id', $id)
->update($response);
}
$results = Character::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new CharacterAnimeCollection(
$results->first()['animeography']
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = CharacterAnimeLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
@ -299,55 +155,8 @@ class CharacterController extends Controller
*/
public function manga(Request $request, int $id)
{
$results = Character::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Character::scrape($id);
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Character::create($response);
}
if ($this->isExpired($request, $results)) {
Character::query()
->where('mal_id', $id)
->update($response);
}
$results = Character::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new CharacterMangaCollection(
$results->first()['mangaography']
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = CharacterMangaLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -376,55 +185,8 @@ class CharacterController extends Controller
*/
public function voices(Request $request, int $id)
{
$results = Character::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Character::scrape($id);
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Character::create($response);
}
if ($this->isExpired($request, $results)) {
Character::query()
->where('mal_id', $id)
->update($response);
}
$results = Character::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new CharacterSeiyuuCollection(
$results->first()['voice_actors']
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = CharacterVoicesLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -432,7 +194,7 @@ class CharacterController extends Controller
* path="/characters/{id}/pictures",
* operationId="getCharacterPictures",
* tags={"characters"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
@ -453,14 +215,14 @@ class CharacterController extends Controller
* description="Error: Bad request. When required parameters were not supplied.",
* ),
* )
*
*
* @OA\Schema(
* schema="character_pictures",
* description="Character Pictures",
* @OA\Property(
* property="data",
* type="array",
*
*
* @OA\Items(
* @OA\Property(
* property="image_url",
@ -480,28 +242,7 @@ class CharacterController extends Controller
*/
public function pictures(Request $request, int $id)
{
$results = DB::table($this->getRouteTable($request))
->where('request_hash', $this->fingerprint)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$character = ['pictures' => $this->jikan->getCharacterPictures(new CharacterPicturesRequest($id))];
$response = \json_decode($this->serializer->serialize($character, 'json'), true);
$results = $this->updateCache($request, $results, $response);
}
$response = (new PicturesResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = CharacterPicturesLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
}

View File

@ -4,6 +4,10 @@ namespace App\Http\Controllers\V4DB;
use App\Anime;
use App\Club;
use App\Dto\ClubLookupCommand;
use App\Dto\ClubMembersLookupCommand;
use App\Dto\ClubRelationLookupCommand;
use App\Dto\ClubStaffLookupCommand;
use App\Http\HttpHelper;
use App\Http\HttpResponse;
use App\Http\Resources\V4\AnimeCharactersResource;
@ -23,7 +27,7 @@ class ClubController extends Controller
* path="/clubs/{id}",
* operationId="getClubsById",
* tags={"clubs"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
@ -49,60 +53,8 @@ class ClubController extends Controller
*/
public function main(Request $request, int $id)
{
$results = Club::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Club::scrape($id);
if (HttpHelper::hasError($response)) {
return HttpResponse::notFound($request);
}
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Club::create($response);
}
if ($this->isExpired($request, $results)) {
Club::query()
->where('mal_id', $id)
->update($response);
}
$results = Club::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new \App\Http\Resources\V4\ClubResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = ClubLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -110,14 +62,14 @@ class ClubController extends Controller
* path="/clubs/{id}/members",
* operationId="getClubMembers",
* tags={"clubs"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* @OA\Schema(type="integer")
* ),
*
*
* @OA\Parameter(ref="#/components/parameters/page"),
*
* @OA\Response(
@ -153,30 +105,8 @@ class ClubController extends Controller
*/
public function members(Request $request, int $id)
{
$results = DB::table($this->getRouteTable($request))
->where('request_hash', $this->fingerprint)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$page = $request->get('page') ?? 1;
$anime = $this->jikan->getClubUsers(new UserListRequest($id, $page));
$response = \json_decode($this->serializer->serialize($anime, 'json'), true);
$results = $this->updateCache($request, $results, $response);
}
$response = (new ResultsResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = ClubMembersLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -207,60 +137,8 @@ class ClubController extends Controller
*/
public function staff(Request $request, int $id)
{
$results = Club::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Club::scrape($id);
if (HttpHelper::hasError($response)) {
return HttpResponse::notFound($request);
}
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Club::create($response);
}
if ($this->isExpired($request, $results)) {
Club::query()
->where('mal_id', $id)
->update($response);
}
$results = Club::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new \App\Http\Resources\V4\ClubStaffResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = ClubStaffLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -291,59 +169,7 @@ class ClubController extends Controller
*/
public function relations(Request $request, int $id)
{
$results = Club::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Club::scrape($id);
if (HttpHelper::hasError($response)) {
return HttpResponse::notFound($request);
}
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Club::create($response);
}
if ($this->isExpired($request, $results)) {
Club::query()
->where('mal_id', $id)
->update($response);
}
$results = Club::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new \App\Http\Resources\V4\ClubRelationsResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = ClubRelationLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
}

View File

@ -2,16 +2,8 @@
namespace App\Http\Controllers\V4DB;
use App\Anime;
use App\GenreAnime;
use App\GenreManga;
use App\Dto\AnimeGenreListCommand;
use App\Http\Resources\V4\GenreCollection;
use App\Http\Resources\V4\MangaCollection;
use App\Manga;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Support\Facades\DB;
class GenreController extends Controller
{
@ -40,40 +32,9 @@ class GenreController extends Controller
* ),
* )
*/
public function anime(Request $request): GenreCollection
public function anime(AnimeGenreListCommand $command): GenreCollection
{
$filter = $request->get('filter') ?? null;
$explicitGenres = DB::table('explicit_genres_anime')->get();
$themes = DB::table('themes_anime')->get();
$demographics = DB::table('demographics_anime')->get();
switch ($filter) {
case 'genres':
$results = GenreAnime::query()
->get();
break;
case 'explicit_genres':
$results = $explicitGenres;
break;
case 'themes':
$results = $themes;
break;
case 'demographics':
$results = $demographics;
break;
default:
$results = GenreAnime::query()
->get()
->concat($explicitGenres->all())
->concat($themes->all())
->concat($demographics->all());
break;
}
return new GenreCollection(
$results
);
return $this->mediator->send($command);
}
/**
@ -102,39 +63,8 @@ class GenreController extends Controller
* ),
* )
*/
public function manga(Request $request): GenreCollection
public function manga(AnimeGenreListCommand $command): GenreCollection
{
$filter = $request->get('filter') ?? null;
$explicitGenres = DB::table('explicit_genres_manga')->get();
$themes = DB::table('themes_manga')->get();
$demographics = DB::table('demographics_manga')->get();
switch ($filter) {
case 'genres':
$results = GenreManga::query()
->get();
break;
case 'explicit_genres':
$results = $explicitGenres;
break;
case 'themes':
$results = $themes;
break;
case 'demographics':
$results = $demographics;
break;
default:
$results = GenreManga::query()
->get()
->concat($explicitGenres->all())
->concat($themes->all())
->concat($demographics->all());
break;
}
return new GenreCollection(
$results
);
return $this->mediator->send($command);
}
}

View File

@ -2,10 +2,10 @@
namespace App\Http\Controllers\V4DB;
use App\Dto\MagazineSearchCommand;
use App\Http\Resources\V4\MagazineCollection;
use Illuminate\Http\Request;
class MagazineController extends ControllerWithQueryBuilderProvider
class MagazineController extends Controller
{
/**
* @OA\Get(
@ -56,8 +56,8 @@ class MagazineController extends ControllerWithQueryBuilderProvider
* )
*
*/
public function main(Request $request): MagazineCollection
public function main(MagazineSearchCommand $command): MagazineCollection
{
return $this->preparePaginatedResponse(MagazineCollection::class, "magazine", $request);
return $this->mediator->send($command);
}
}

View File

@ -2,39 +2,20 @@
namespace App\Http\Controllers\V4DB;
use App\Helpers\ScraperHelper;
use App\Http\HttpHelper;
use App\Http\HttpResponse;
use App\Http\QueryBuilder\Scraper\Query;
use App\Http\QueryBuilder\Scraper\QueryResolver;
use App\Http\QueryBuilder\Scraper\ScraperHandler;
use App\Http\Resources\V4\ExternalLinksResource;
use App\Http\Resources\V4\MangaRelationsResource;
use App\Http\Resources\V4\ResultsResource;
use App\Http\Resources\V4\ReviewsResource;
use App\Http\Resources\V4\RecommendationsResource;
use App\Http\Resources\V4\MoreInfoResource;
use App\Http\Resources\V4\ForumResource;
use App\Http\Resources\V4\MangaCharactersResource;
use App\Http\Resources\V4\MangaStatisticsResource;
use App\Http\Resources\V4\PicturesResource;
use App\Http\Validation\ValidationTypeEnum;
use App\Manga;
use App\Dto\MangaCharactersLookupCommand;
use App\Dto\MangaExternalLookupCommand;
use App\Dto\MangaForumLookupCommand;
use App\Dto\MangaFullLookupCommand;
use App\Dto\MangaLookupCommand;
use App\Dto\MangaMoreInfoLookupCommand;
use App\Dto\MangaNewsLookupCommand;
use App\Dto\MangaPicturesLookupCommand;
use App\Dto\MangaRecommendationsLookupCommand;
use App\Dto\MangaRelationsLookupCommand;
use App\Dto\MangaReviewsLookupCommand;
use App\Dto\MangaStatsLookupCommand;
use App\Dto\MangaUserUpdatesLookupCommand;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Jikan\Exception\BadResponseException;
use Jikan\Helper\Constants;
use Jikan\Request\Manga\MangaCharactersRequest;
use Jikan\Request\Manga\MangaForumRequest;
use Jikan\Request\Manga\MangaMoreInfoRequest;
use Jikan\Request\Manga\MangaNewsRequest;
use Jikan\Request\Manga\MangaPicturesRequest;
use Jikan\Request\Manga\MangaRecentlyUpdatedByUsersRequest;
use Jikan\Request\Manga\MangaRecommendationsRequest;
use Jikan\Request\Manga\MangaReviewsRequest;
use Jikan\Request\Manga\MangaStatsRequest;
use MongoDB\BSON\UTCDateTime;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
class MangaController extends Controller
{
@ -70,60 +51,8 @@ class MangaController extends Controller
*/
public function full(Request $request, int $id)
{
$results = Manga::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Manga::scrape($id);
if (HttpHelper::hasError($response)) {
return HttpResponse::notFound($request);
}
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Manga::create($response);
}
if ($this->isExpired($request, $results)) {
Manga::query()
->where('mal_id', $id)
->update($response);
}
$results = Manga::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new \App\Http\Resources\V4\MangaFullResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaFullLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -158,60 +87,8 @@ class MangaController extends Controller
*/
public function main(Request $request, int $id)
{
$results = Manga::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Manga::scrape($id);
if (HttpHelper::hasError($response)) {
return HttpResponse::notFound($request);
}
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Manga::create($response);
}
if ($this->isExpired($request, $results)) {
Manga::query()
->where('mal_id', $id)
->update($response);
}
$results = Manga::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new \App\Http\Resources\V4\MangaResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -242,29 +119,8 @@ class MangaController extends Controller
*/
public function characters(Request $request, int $id)
{
$results = DB::table($this->getRouteTable($request))
->where('request_hash', $this->fingerprint)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$manga = ['characters' => $this->jikan->getMangaCharacters(new MangaCharactersRequest($id))];
$response = \json_decode($this->serializer->serialize($manga, 'json'), true);
$results = $this->updateCache($request, $results, $response);
}
$response = (new MangaCharactersResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaCharactersLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -307,30 +163,8 @@ class MangaController extends Controller
*/
public function news(Request $request, int $id)
{
$results = DB::table($this->getRouteTable($request))
->where('request_hash', $this->fingerprint)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$page = $request->get('page') ?? 1;
$manga = $this->jikan->getNewsList(new MangaNewsRequest($id, $page));
$response = \json_decode($this->serializer->serialize($manga, 'json'), true);
$results = $this->updateCache($request, $results, $response);
}
$response = (new ResultsResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaNewsLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -369,35 +203,8 @@ class MangaController extends Controller
*/
public function forum(Request $request, int $id)
{
$results = DB::table($this->getRouteTable($request))
->where('request_hash', $this->fingerprint)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$topic = $request->get('topic');
if ($request->get('filter') != null) {
$topic = $request->get('filter');
}
$manga = ['topics' => $this->jikan->getMangaForum(new MangaForumRequest($id, $topic))];
$response = \json_decode($this->serializer->serialize($manga, 'json'), true);
$results = $this->updateCache($request, $results, $response);
}
$response = (new ForumResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaForumLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -441,29 +248,8 @@ class MangaController extends Controller
*/
public function pictures(Request $request, int $id)
{
$results = DB::table($this->getRouteTable($request))
->where('request_hash', $this->fingerprint)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$manga = ['pictures' => $this->jikan->getMangaPictures(new MangaPicturesRequest($id))];
$response = \json_decode($this->serializer->serialize($manga, 'json'), true);
$results = $this->updateCache($request, $results, $response);
}
$response = (new PicturesResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaPicturesLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -494,29 +280,8 @@ class MangaController extends Controller
*/
public function stats(Request $request, int $id)
{
$results = DB::table($this->getRouteTable($request))
->where('request_hash', $this->fingerprint)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$manga = $this->jikan->getMangaStats(new MangaStatsRequest($id));
$response = \json_decode($this->serializer->serialize($manga, 'json'), true);
$results = $this->updateCache($request, $results, $response);
}
$response = (new MangaStatisticsResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaStatsLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -547,29 +312,8 @@ class MangaController extends Controller
*/
public function moreInfo(Request $request, int $id)
{
$results = DB::table($this->getRouteTable($request))
->where('request_hash', $this->fingerprint)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$manga = ['moreinfo' => $this->jikan->getMangaMoreInfo(new MangaMoreInfoRequest($id))];
$response = \json_decode($this->serializer->serialize($manga, 'json'), true);
$results = $this->updateCache($request, $results, $response);
}
$response = (new MoreInfoResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaMoreInfoLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -600,29 +344,8 @@ class MangaController extends Controller
*/
public function recommendations(Request $request, int $id)
{
$results = DB::table($this->getRouteTable($request))
->where('request_hash', $this->fingerprint)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$manga = ['recommendations' => $this->jikan->getMangaRecommendations(new MangaRecommendationsRequest($id))];
$response = \json_decode($this->serializer->serialize($manga, 'json'), true);
$results = $this->updateCache($request, $results, $response);
}
$response = (new RecommendationsResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaRecommendationsLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -655,30 +378,8 @@ class MangaController extends Controller
*/
public function userupdates(Request $request, int $id)
{
$results = DB::table($this->getRouteTable($request))
->where('request_hash', $this->fingerprint)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$page = $request->get('page') ?? 1;
$manga = $this->jikan->getMangaRecentlyUpdatedByUsers(new MangaRecentlyUpdatedByUsersRequest($id, $page));
$response = \json_decode($this->serializer->serialize($manga, 'json'), true);
$results = $this->updateCache($request, $results, $response);
}
$response = (new ResultsResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaUserUpdatesLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -712,50 +413,8 @@ class MangaController extends Controller
*/
public function reviews(Request $request, int $id)
{
$validation = $this->validate($request, [
'page' => 'nullable|numeric',
'sort' => 'nullable|string'
]);
$page = $request->get('page') ?? 1;
$spoilers = $request->get('spoilers') ?? false;
$preliminary = $request->get('preliminary') ?? false;
$sort = $request->get('sort');
$results = DB::table($this->getRouteTable($request))
->where('request_hash', $this->fingerprint)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = ScraperHelper::getSerializedJSON(
app('JikanParser')
->getMangaReviews(
new MangaReviewsRequest(
$id,
$page,
in_array($sort, [Constants::REVIEWS_SORT_MOST_VOTED, Constants::REVIEWS_SORT_NEWEST, Constants::REVIEWS_SORT_OLDEST]) ? $sort : Constants::REVIEWS_SORT_MOST_VOTED,
$spoilers,
$preliminary
)
)
);
$results = $this->updateCache($request, $results, $response);
}
$response = (new ReviewsResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaReviewsLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -793,56 +452,8 @@ class MangaController extends Controller
*/
public function relations(Request $request, int $id)
{
$results = Manga::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Manga::scrape($id);
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Manga::create($response);
}
if ($this->isExpired($request, $results)) {
Manga::query()
->where('mal_id', $id)
->update($response);
}
$results = Manga::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new MangaRelationsResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaRelationsLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
/**
@ -873,54 +484,7 @@ class MangaController extends Controller
*/
public function external(Request $request, int $id)
{
$results = Manga::query()
->where('mal_id', $id)
->get();
if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
$response = Manga::scrape($id);
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$response = $meta + $response;
if ($results->isEmpty()) {
Manga::create($response);
}
if ($this->isExpired($request, $results)) {
Manga::query()
->where('mal_id', $id)
->update($response);
}
$results = Manga::query()
->where('mal_id', $id)
->get();
}
if ($results->isEmpty()) {
return HttpResponse::notFound($request);
}
$response = (new ExternalLinksResource(
$results->first()
))->response();
return $this->prepareResponse(
$response,
$results,
$request
);
$command = MangaExternalLookupCommand::from($request, $id);
return $this->mediator->send($command);
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Macros;
use Illuminate\Support\Collection;
/**
* @mixin Collection
* @method offsetGetFirst(string $offset, mixed $default = null)
*/
final class CollectionOffsetGetFirst
{
public function __invoke(): \Closure
{
return function (string $offset, mixed $default = null) {
/**
* @var $this Collection
*/
$firstItem = $this->first();
if (is_array($firstItem)) {
$result = collect($firstItem)->get($offset, $default);
} else {
$result = $default;
}
return $result;
};
}
}

View File

@ -3,7 +3,7 @@ namespace App\Macros;
use Illuminate\Support\Collection;
class To2dArrayWithDottedKeys
final class To2dArrayWithDottedKeys
{
public function __invoke(): \Closure
{

View File

@ -15,41 +15,6 @@ use App\Contracts\Repository;
use App\Contracts\RequestHandler;
use App\Contracts\UnitOfWork;
use App\Contracts\UserRepository;
use App\Dto\QueryTopPeopleCommand;
use App\Features\AnimeEpisodeLookupHandler;
use App\Features\AnimeEpisodesLookupHandler;
use App\Features\AnimeExternalLookupHandler;
use App\Features\AnimeForumLookupHandler;
use App\Features\AnimeGenreListHandler;
use App\Features\AnimeMoreInfoLookupHandler;
use App\Features\AnimeNewsLookupHandler;
use App\Features\AnimePicturesLookupHandler;
use App\Features\AnimeRecommendationsLookupHandler;
use App\Features\AnimeRelationsLookupHandler;
use App\Features\AnimeReviewsLookupHandler;
use App\Features\AnimeSearchHandler;
use App\Features\AnimeCharactersLookupHandler;
use App\Features\AnimeStaffLookupHandler;
use App\Features\AnimeStatsLookupHandler;
use App\Features\AnimeStreamingLookupHandler;
use App\Features\AnimeThemesLookupHandler;
use App\Features\AnimeVideosEpisodesLookupHandler;
use App\Features\AnimeVideosLookupHandler;
use App\Features\CharacterSearchHandler;
use App\Features\ClubSearchHandler;
use App\Features\MagazineSearchHandler;
use App\Features\MangaGenreListHandler;
use App\Features\MangaSearchHandler;
use App\Features\PeopleSearchHandler;
use App\Features\ProducerSearchHandler;
use App\Features\QueryAnimeHandler;
use App\Features\QueryFullAnimeHandler;
use App\Features\QueryTopAnimeItemsHandler;
use App\Features\QueryTopCharactersHandler;
use App\Features\QueryTopMangaItemsHandler;
use App\Features\QueryTopReviewsHandler;
use App\Features\UserByIdLookupHandler;
use App\Features\UserSearchHandler;
use App\GenreAnime;
use App\GenreManga;
use App\Http\QueryBuilder\AnimeSearchQueryBuilder;
@ -60,6 +25,7 @@ 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\To2dArrayWithDottedKeys;
use App\Magazine;
use App\Mixins\ScoutBuilderMixin;
@ -88,11 +54,13 @@ use App\Support\DefaultMediator;
use App\Support\JikanUnitOfWork;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Env;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Collection;
use Jikan\MyAnimeList\MalClient;
use Laravel\Scout\Builder as ScoutBuilder;
use Typesense\LaravelTypesense\Typesense;
use App\Features;
class AppServiceProvider extends ServiceProvider
{
@ -194,6 +162,11 @@ class AppServiceProvider extends ServiceProvider
$this->app->singleton(SearchQueryBuilderProvider::class, function($app) {
return new SearchQueryBuilderProvider($app->tagged("searchQueryBuilders"));
});
// new stuff
$this->app->singleton(CachedScraperService::class, DefaultCachedScraperService::class);
$this->registerModelRepositories();
$this->registerRequestHandlers();
}
private function registerModelRepositories()
@ -219,7 +192,6 @@ class AppServiceProvider extends ServiceProvider
$this->app->singleton(MangaGenresRepository::class);
$this->app->singleton(UnitOfWork::class, JikanUnitOfWork::class);
$this->app->singleton(CachedScraperService::class, DefaultCachedScraperService::class);
}
private function registerRequestHandlers()
@ -229,12 +201,13 @@ class AppServiceProvider extends ServiceProvider
*/
$this->app->singleton(Mediator::class, DefaultMediator::class);
/*
* Contextual binding for the mediator.
* Each request is represented as a data transfer object, and spatie/laravel-data package's service provider
* registers them in the ioc container. For each request there is a request handler.
* Validation for requests is specified in the DTOs.
* Querying/Filtering entirely happens on the model side.
* The lines below explicitly define the mapping between request handlers and repositories.
* Repositories are just a bit of abstraction over models.
* Repositories are just a bit of abstraction over models. They are making unit testing easier.
*/
$this->app->when(DefaultMediator::class)
->needs(RequestHandler::class)
@ -245,13 +218,13 @@ class AppServiceProvider extends ServiceProvider
*/
$unitOfWorkInstance = $app->make(UnitOfWork::class);
$searchRequestHandlersDescriptors = [
AnimeSearchHandler::class => $unitOfWorkInstance->anime(),
MangaSearchHandler::class => $unitOfWorkInstance->manga(),
CharacterSearchHandler::class => $unitOfWorkInstance->characters(),
PeopleSearchHandler::class => $unitOfWorkInstance->people(),
ClubSearchHandler::class => $unitOfWorkInstance->clubs(),
MagazineSearchHandler::class => $unitOfWorkInstance->magazines(),
ProducerSearchHandler::class => $unitOfWorkInstance->producers(),
Features\AnimeSearchHandler::class => $unitOfWorkInstance->anime(),
Features\MangaSearchHandler::class => $unitOfWorkInstance->manga(),
Features\CharacterSearchHandler::class => $unitOfWorkInstance->characters(),
Features\PeopleSearchHandler::class => $unitOfWorkInstance->people(),
Features\ClubSearchHandler::class => $unitOfWorkInstance->clubs(),
Features\MagazineSearchHandler::class => $unitOfWorkInstance->magazines(),
Features\ProducerSearchHandler::class => $unitOfWorkInstance->producers(),
];
$requestHandlers = [];
foreach ($searchRequestHandlersDescriptors as $handlerClass => $repositoryInstance) {
@ -264,10 +237,10 @@ class AppServiceProvider extends ServiceProvider
}
$queryTopItemsDescriptors = [
QueryTopAnimeItemsHandler::class => $unitOfWorkInstance->anime(),
QueryTopMangaItemsHandler::class => $unitOfWorkInstance->manga(),
QueryTopCharactersHandler::class => $unitOfWorkInstance->characters(),
QueryTopPeopleCommand::class => $unitOfWorkInstance->people(),
Features\QueryTopAnimeItemsHandler::class => $unitOfWorkInstance->anime(),
Features\QueryTopMangaItemsHandler::class => $unitOfWorkInstance->manga(),
Features\QueryTopCharactersHandler::class => $unitOfWorkInstance->characters(),
Features\QueryTopPeopleHandler::class => $unitOfWorkInstance->people(),
];
foreach ($queryTopItemsDescriptors as $handlerClass => $repositoryInstance) {
@ -280,8 +253,8 @@ class AppServiceProvider extends ServiceProvider
// request handlers which only depend on a repository instance
$requestHandlersWithOnlyRepositoryDependency = [
AnimeGenreListHandler::class => $unitOfWorkInstance->animeGenres(),
MangaGenreListHandler::class => $unitOfWorkInstance->mangaGenres(),
Features\AnimeGenreListHandler::class => $unitOfWorkInstance->animeGenres(),
Features\MangaGenreListHandler::class => $unitOfWorkInstance->mangaGenres(),
];
foreach ($requestHandlersWithOnlyRepositoryDependency as $handlerClass => $repositoryInstance) {
@ -290,28 +263,51 @@ class AppServiceProvider extends ServiceProvider
// request handlers which are fetching data through the jikan library from MAL, and caching the result.
$requestHandlersWithScraperService = [
QueryFullAnimeHandler::class => $unitOfWorkInstance->anime(),
QueryAnimeHandler::class => $unitOfWorkInstance->anime(),
UserSearchHandler::class => $unitOfWorkInstance->documents("common"),
QueryTopReviewsHandler::class => $unitOfWorkInstance->documents("common"),
UserByIdLookupHandler::class => $unitOfWorkInstance->documents("common"),
AnimeCharactersLookupHandler::class => $unitOfWorkInstance->documents("anime_characters_staff"),
AnimeStaffLookupHandler::class => $unitOfWorkInstance->documents("anime_characters_staff"),
AnimeEpisodesLookupHandler::class => $unitOfWorkInstance->documents("anime_episodes"),
AnimeEpisodeLookupHandler::class => $unitOfWorkInstance->documents("anime_episode"),
AnimeNewsLookupHandler::class => $unitOfWorkInstance->documents("anime_news"),
AnimeForumLookupHandler::class => $unitOfWorkInstance->documents("anime_forum"),
AnimeVideosLookupHandler::class => $unitOfWorkInstance->documents("anime_videos"),
AnimeVideosEpisodesLookupHandler::class => $unitOfWorkInstance->documents("anime_videos_episodes"),
AnimePicturesLookupHandler::class => $unitOfWorkInstance->documents("anime_pictures"),
AnimeStatsLookupHandler::class => $unitOfWorkInstance->documents("anime_stats"),
AnimeMoreInfoLookupHandler::class => $unitOfWorkInstance->documents("anime_moreinfo"),
AnimeRecommendationsLookupHandler::class => $unitOfWorkInstance->documents("anime_recommendations"),
AnimeReviewsLookupHandler::class => $unitOfWorkInstance->documents("anime_reviews"),
AnimeRelationsLookupHandler::class => $unitOfWorkInstance->anime(),
AnimeExternalLookupHandler::class => $unitOfWorkInstance->anime(),
AnimeStreamingLookupHandler::class => $unitOfWorkInstance->anime(),
AnimeThemesLookupHandler::class => $unitOfWorkInstance->anime(),
Features\AnimeFullLookupHandler::class => $unitOfWorkInstance->anime(),
Features\AnimeLookupHandler::class => $unitOfWorkInstance->anime(),
Features\UserSearchHandler::class => $unitOfWorkInstance->documents("common"),
Features\QueryTopReviewsHandler::class => $unitOfWorkInstance->documents("common"),
Features\UserByIdLookupHandler::class => $unitOfWorkInstance->documents("common"),
Features\AnimeCharactersLookupHandler::class => $unitOfWorkInstance->documents("anime_characters_staff"),
Features\AnimeStaffLookupHandler::class => $unitOfWorkInstance->documents("anime_characters_staff"),
Features\AnimeEpisodesLookupHandler::class => $unitOfWorkInstance->documents("anime_episodes"),
Features\AnimeEpisodeLookupHandler::class => $unitOfWorkInstance->documents("anime_episode"),
Features\AnimeNewsLookupHandler::class => $unitOfWorkInstance->documents("anime_news"),
Features\AnimeForumLookupHandler::class => $unitOfWorkInstance->documents("anime_forum"),
Features\AnimeVideosLookupHandler::class => $unitOfWorkInstance->documents("anime_videos"),
Features\AnimeVideosEpisodesLookupHandler::class => $unitOfWorkInstance->documents("anime_videos_episodes"),
Features\AnimePicturesLookupHandler::class => $unitOfWorkInstance->documents("anime_pictures"),
Features\AnimeStatsLookupHandler::class => $unitOfWorkInstance->documents("anime_stats"),
Features\AnimeMoreInfoLookupHandler::class => $unitOfWorkInstance->documents("anime_moreinfo"),
Features\AnimeRecommendationsLookupHandler::class => $unitOfWorkInstance->documents("anime_recommendations"),
Features\AnimeReviewsLookupHandler::class => $unitOfWorkInstance->documents("anime_reviews"),
Features\AnimeRelationsLookupHandler::class => $unitOfWorkInstance->anime(),
Features\AnimeExternalLookupHandler::class => $unitOfWorkInstance->anime(),
Features\AnimeStreamingLookupHandler::class => $unitOfWorkInstance->anime(),
Features\AnimeThemesLookupHandler::class => $unitOfWorkInstance->anime(),
Features\CharacterLookupHandler::class => $unitOfWorkInstance->characters(),
Features\CharacterFullLookupHandler::class => $unitOfWorkInstance->characters(),
Features\CharacterAnimeLookupHandler::class => $unitOfWorkInstance->characters(),
Features\CharacterMangaLookupHandler::class => $unitOfWorkInstance->characters(),
Features\CharacterVoicesLookupHandler::class => $unitOfWorkInstance->characters(),
Features\CharacterPicturesLookupHandler::class => $unitOfWorkInstance->documents("characters_pictures"),
Features\ClubLookupHandler::class => $unitOfWorkInstance->clubs(),
Features\ClubMembersLookupHandler::class => $unitOfWorkInstance->documents("clubs_members"),
Features\ClubStaffLookupHandler::class => $unitOfWorkInstance->clubs(),
Features\ClubRelationsLookupHandler::class => $unitOfWorkInstance->clubs(),
Features\MangaCharactersLookupHandler::class => $unitOfWorkInstance->documents("manga_characters"),
Features\MangaNewsLookupHandler::class => $unitOfWorkInstance->documents("manga_news"),
Features\MangaForumLookupHandler::class => $unitOfWorkInstance->documents("manga_forum"),
Features\MangaPicturesLookupHandler::class => $unitOfWorkInstance->documents("manga_pictures"),
Features\MangaStatsLookupHandler::class => $unitOfWorkInstance->documents("manga_stats"),
Features\MangaMoreInfoLookupHandler::class => $unitOfWorkInstance->documents("manga_moreinfo"),
Features\MangaRecommendationsLookupHandler::class => $unitOfWorkInstance->documents("manga_recommendations"),
Features\MangaUserUpdatesLookupHandler::class => $unitOfWorkInstance->documents("manga_userupdates"),
Features\MangaReviewsLookupHandler::class => $unitOfWorkInstance->documents("manga_reviews"),
Features\MangaLookupHandler::class => $unitOfWorkInstance->manga(),
Features\MangaFullLookupHandler::class => $unitOfWorkInstance->manga(),
Features\MangaRelationsLookupHandler::class => $unitOfWorkInstance->manga(),
Features\MangaExternalLookupHandler::class => $unitOfWorkInstance->manga()
];
foreach ($requestHandlersWithScraperService as $handlerClass => $repositoryInstance) {
@ -382,7 +378,8 @@ class AppServiceProvider extends ServiceProvider
private function collectionMacros(): array
{
return [
"to2dArrayWithDottedKeys" => To2dArrayWithDottedKeys::class
"to2dArrayWithDottedKeys" => To2dArrayWithDottedKeys::class,
"offsetGetFirst" => CollectionOffsetGetFirst::class
];
}
@ -417,11 +414,11 @@ class AppServiceProvider extends ServiceProvider
TopMangaQueryBuilder::class
];
if (env("SCOUT_DRIVER") === "typesense") {
if (Env::get("SCOUT_DRIVER") === "typesense") {
$services[] = Typesense::class;
}
if (env("SCOUT_DRIVER") === "Matchish\ScoutElasticSearch\Engines\ElasticSearchEngine") {
if (Env::get("SCOUT_DRIVER") === "Matchish\ScoutElasticSearch\Engines\ElasticSearchEngine") {
$services[] = \Elastic\Elasticsearch\Client::class;
}

View File

@ -46,7 +46,7 @@ final class DefaultCachedScraperService implements CachedScraperService
if ($results->isEmpty() || $results->isExpired()) {
$page = $page ?? 1;
$data = $getMalDataCallback($this->jikan, $page);
$scraperResponse = $this->serializeScraperResult($data);
$scraperResponse = $this->serializeScraperResult(Collection::unwrap($data));
$results = $this->updateCacheByKey($cacheKey, $results, $scraperResponse);
}
@ -191,7 +191,7 @@ final class DefaultCachedScraperService implements CachedScraperService
return $this->repository->where("request_hash", $cacheKey);
}
private function serializeScraperResult($data): array
private function serializeScraperResult(array $data): array
{
return $this->serializer->toArray($data);
}