mirror of
https://github.com/jikan-me/jikan-rest.git
synced 2025-02-20 11:23:35 +08:00
wip - more fixes
- added user animelist/mangalist endpoints back - fixed issues with the container image - improved club model factory - fixed ordering while searching when search engine is disabled (mongodb based search)
This commit is contained in:
parent
7ac4f8693e
commit
fbc3b8277d
87
app/Dto/QueryAnimeListOfUserCommand.php
Normal file
87
app/Dto/QueryAnimeListOfUserCommand.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace App\Dto;
|
||||
|
||||
use App\Casts\EnumCast;
|
||||
use App\Enums\AnimeListAiringStatusFilterEnum;
|
||||
use App\Enums\AnimeListStatusEnum;
|
||||
use App\Enums\UserAnimeListOrderByEnum;
|
||||
use App\Enums\UserListTypeEnum;
|
||||
use App\Rules\Attributes\EnumValidation;
|
||||
use App\Services\JikanUserListRequestMapperService;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Jikan\Request\User\UserAnimeListRequest;
|
||||
use Spatie\LaravelData\Attributes\MapInputName;
|
||||
use Spatie\LaravelData\Attributes\Validation\AfterOrEqual;
|
||||
use Spatie\LaravelData\Attributes\Validation\BeforeOrEqual;
|
||||
use Spatie\LaravelData\Attributes\Validation\DateFormat;
|
||||
use Spatie\LaravelData\Attributes\Validation\Max;
|
||||
use Spatie\LaravelData\Attributes\Validation\Min;
|
||||
use Spatie\LaravelData\Attributes\Validation\Required;
|
||||
use Spatie\LaravelData\Attributes\Validation\Sometimes;
|
||||
use Spatie\LaravelData\Attributes\WithCast;
|
||||
use Spatie\LaravelData\Attributes\WithTransformer;
|
||||
use Spatie\LaravelData\Casts\DateTimeInterfaceCast;
|
||||
use Spatie\LaravelData\Optional;
|
||||
use Spatie\LaravelData\Transformers\DateTimeInterfaceTransformer;
|
||||
|
||||
final class QueryAnimeListOfUserCommand extends QueryListOfUserCommand
|
||||
{
|
||||
#[WithCast(EnumCast::class, AnimeListStatusEnum::class), EnumValidation(AnimeListStatusEnum::class)]
|
||||
public AnimeListStatusEnum|Optional $status;
|
||||
|
||||
#[
|
||||
WithCast(EnumCast::class, UserAnimeListOrderByEnum::class),
|
||||
EnumValidation(UserAnimeListOrderByEnum::class),
|
||||
MapInputName("order_by")
|
||||
]
|
||||
public UserAnimeListOrderByEnum|Optional $orderBy;
|
||||
|
||||
#[
|
||||
WithCast(EnumCast::class, UserAnimeListOrderByEnum::class),
|
||||
EnumValidation(UserAnimeListOrderByEnum::class),
|
||||
MapInputName("order_by2")
|
||||
]
|
||||
public UserAnimeListOrderByEnum|Optional $orderBy2;
|
||||
|
||||
#[
|
||||
WithCast(EnumCast::class, AnimeListAiringStatusFilterEnum::class),
|
||||
EnumValidation(AnimeListAiringStatusFilterEnum::class),
|
||||
MapInputName("airing_status")
|
||||
]
|
||||
public AnimeListAiringStatusFilterEnum|Optional $airingStatus;
|
||||
|
||||
#[Min(1500), Max(2999)]
|
||||
public int|Optional $year;
|
||||
|
||||
#[Min(1)]
|
||||
public int|Optional $producer;
|
||||
|
||||
#[
|
||||
BeforeOrEqual("aired_to"),
|
||||
DateFormat("Y-m-d"),
|
||||
Sometimes,
|
||||
Required,
|
||||
WithCast(DateTimeInterfaceCast::class),
|
||||
WithTransformer(DateTimeInterfaceTransformer::class),
|
||||
MapInputName("aired_from")
|
||||
]
|
||||
public CarbonImmutable|Optional $airedFrom;
|
||||
|
||||
#[
|
||||
AfterOrEqual("aired_from"),
|
||||
DateFormat("Y-m-d"),
|
||||
Sometimes,
|
||||
Required,
|
||||
WithCast(DateTimeInterfaceCast::class),
|
||||
WithTransformer(DateTimeInterfaceTransformer::class),
|
||||
MapInputName("aired_to")
|
||||
]
|
||||
public CarbonImmutable|Optional $airedTo;
|
||||
|
||||
public function toJikanParserRequest(): UserAnimeListRequest
|
||||
{
|
||||
$mapper = app(JikanUserListRequestMapperService::class);
|
||||
return $mapper->map($this, UserListTypeEnum::anime());
|
||||
}
|
||||
}
|
36
app/Dto/QueryListOfUserCommand.php
Normal file
36
app/Dto/QueryListOfUserCommand.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Dto;
|
||||
|
||||
|
||||
use App\Casts\EnumCast;
|
||||
use App\Concerns\HasRequestFingerprint;
|
||||
use App\Contracts\DataRequest;
|
||||
use App\Dto\Concerns\HasPageParameter;
|
||||
use App\Dto\Concerns\MapsRouteParameters;
|
||||
use App\Enums\SortDirection;
|
||||
use App\Rules\Attributes\EnumValidation;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Spatie\LaravelData\Attributes\MapOutputName;
|
||||
use Spatie\LaravelData\Attributes\Validation\Max;
|
||||
use Spatie\LaravelData\Attributes\Validation\Min;
|
||||
use Spatie\LaravelData\Attributes\WithCast;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\Optional;
|
||||
|
||||
/**
|
||||
* @implements DataRequest<JsonResponse>
|
||||
*/
|
||||
abstract class QueryListOfUserCommand extends Data implements DataRequest
|
||||
{
|
||||
use HasRequestFingerprint, HasPageParameter, MapsRouteParameters;
|
||||
|
||||
#[Min(3)]
|
||||
public string $username;
|
||||
|
||||
#[Max(255), MapOutputName("title")]
|
||||
public string|Optional $q;
|
||||
|
||||
#[WithCast(EnumCast::class, SortDirection::class), EnumValidation(SortDirection::class)]
|
||||
public SortDirection|Optional $sort;
|
||||
}
|
84
app/Dto/QueryMangaListOfUserCommand.php
Normal file
84
app/Dto/QueryMangaListOfUserCommand.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace App\Dto;
|
||||
|
||||
use App\Casts\EnumCast;
|
||||
use App\Enums\MangaListStatusEnum;
|
||||
use App\Enums\UserListTypeEnum;
|
||||
use App\Enums\UserMangaListOrderByEnum;
|
||||
use App\Enums\UserMangaListStatusFilterEnum;
|
||||
use App\Rules\Attributes\EnumValidation;
|
||||
use App\Services\JikanUserListRequestMapperService;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Jikan\Request\User\UserMangaListRequest;
|
||||
use Spatie\LaravelData\Attributes\MapInputName;
|
||||
use Spatie\LaravelData\Attributes\Validation\AfterOrEqual;
|
||||
use Spatie\LaravelData\Attributes\Validation\BeforeOrEqual;
|
||||
use Spatie\LaravelData\Attributes\Validation\DateFormat;
|
||||
use Spatie\LaravelData\Attributes\Validation\Min;
|
||||
use Spatie\LaravelData\Attributes\Validation\Required;
|
||||
use Spatie\LaravelData\Attributes\Validation\Sometimes;
|
||||
use Spatie\LaravelData\Attributes\WithCast;
|
||||
use Spatie\LaravelData\Attributes\WithTransformer;
|
||||
use Spatie\LaravelData\Casts\DateTimeInterfaceCast;
|
||||
use Spatie\LaravelData\Optional;
|
||||
use Spatie\LaravelData\Transformers\DateTimeInterfaceTransformer;
|
||||
|
||||
final class QueryMangaListOfUserCommand extends QueryListOfUserCommand
|
||||
{
|
||||
#[WithCast(EnumCast::class, MangaListStatusEnum::class), EnumValidation(MangaListStatusEnum::class)]
|
||||
public MangaListStatusEnum|Optional $status;
|
||||
|
||||
#[
|
||||
WithCast(EnumCast::class, UserMangaListOrderByEnum::class),
|
||||
MapInputName("order_by"),
|
||||
EnumValidation(UserMangaListOrderByEnum::class)
|
||||
]
|
||||
public UserMangaListOrderByEnum|Optional $orderBy;
|
||||
|
||||
#[
|
||||
WithCast(EnumCast::class, UserMangaListOrderByEnum::class),
|
||||
MapInputName("order_by2"),
|
||||
EnumValidation(UserMangaListOrderByEnum::class)
|
||||
]
|
||||
public UserMangaListOrderByEnum|Optional $orderBy2;
|
||||
|
||||
#[Min(1)]
|
||||
public int|Optional $magazine;
|
||||
|
||||
#[
|
||||
BeforeOrEqual("published_to"),
|
||||
DateFormat("Y-m-d"),
|
||||
Sometimes,
|
||||
Required,
|
||||
WithCast(DateTimeInterfaceCast::class),
|
||||
WithTransformer(DateTimeInterfaceTransformer::class),
|
||||
MapInputName("published_from")
|
||||
]
|
||||
public CarbonImmutable|Optional $publishedFrom;
|
||||
|
||||
#[
|
||||
AfterOrEqual("published_from"),
|
||||
DateFormat("Y-m-d"),
|
||||
Sometimes,
|
||||
Required,
|
||||
WithCast(DateTimeInterfaceCast::class),
|
||||
WithTransformer(DateTimeInterfaceTransformer::class),
|
||||
MapInputName("published_to")
|
||||
]
|
||||
public CarbonImmutable|Optional $publishedTo;
|
||||
|
||||
#[
|
||||
WithCast(EnumCast::class, UserMangaListStatusFilterEnum::class),
|
||||
EnumValidation(UserMangaListStatusFilterEnum::class),
|
||||
MapInputName("publishing_status")
|
||||
]
|
||||
public UserMangaListStatusFilterEnum|Optional $publishingStatus;
|
||||
|
||||
|
||||
public function toJikanParserRequest(): UserMangaListRequest
|
||||
{
|
||||
$mapper = app(JikanUserListRequestMapperService::class);
|
||||
return $mapper->map($this, UserListTypeEnum::manga());
|
||||
}
|
||||
}
|
32
app/Enums/AnimeListAiringStatusFilterEnum.php
Normal file
32
app/Enums/AnimeListAiringStatusFilterEnum.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
|
||||
use Spatie\Enum\Laravel\Enum;
|
||||
use Jikan\Helper\Constants as JikanConstants;
|
||||
|
||||
/**
|
||||
* @method static self airing()
|
||||
* @method static self finished()
|
||||
* @method static self complete()
|
||||
* @method static self to_be_aired()
|
||||
* @method static self not_yet_aired()
|
||||
* @method static self tba()
|
||||
* @method static self nya()
|
||||
*/
|
||||
final class AnimeListAiringStatusFilterEnum extends Enum
|
||||
{
|
||||
protected static function labels()
|
||||
{
|
||||
return [
|
||||
'airing' => JikanConstants::USER_ANIME_LIST_CURRENTLY_AIRING,
|
||||
'finished' => JikanConstants::USER_ANIME_LIST_FINISHED_AIRING,
|
||||
'complete' => JikanConstants::USER_ANIME_LIST_FINISHED_AIRING,
|
||||
'to_be_aired' => JikanConstants::USER_ANIME_LIST_NOT_YET_AIRED,
|
||||
'not_yet_aired' => JikanConstants::USER_ANIME_LIST_NOT_YET_AIRED,
|
||||
'tba' => JikanConstants::USER_ANIME_LIST_NOT_YET_AIRED,
|
||||
'nya' => JikanConstants::USER_ANIME_LIST_NOT_YET_AIRED,
|
||||
];
|
||||
}
|
||||
}
|
38
app/Enums/AnimeListStatusEnum.php
Normal file
38
app/Enums/AnimeListStatusEnum.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
|
||||
use Spatie\Enum\Laravel\Enum;
|
||||
|
||||
/**
|
||||
* @method static self all()
|
||||
* @method static self watching()
|
||||
* @method static self completed()
|
||||
* @method static self onhold()
|
||||
* @method static self dropped()
|
||||
* @method static self plantowatch()
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="user_anime_list_status_filter",
|
||||
* description="User's anime list status filter options",
|
||||
* type="string",
|
||||
* enum={"all", "watching", "completed", "onhold", "dropped", "plantowatch"}
|
||||
* )
|
||||
*/
|
||||
final class AnimeListStatusEnum extends Enum
|
||||
{
|
||||
// labels will be the values used for mapping, meanwhile the values are the names of the enum elements,
|
||||
// because these are getting passed in through the query string in requests, and we validate against them
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
"all" => "7",
|
||||
"watching" => "1",
|
||||
"completed" => "2",
|
||||
"onhold" => "3",
|
||||
"dropped" => "4",
|
||||
"plantowatch" => "6"
|
||||
];
|
||||
}
|
||||
}
|
38
app/Enums/MangaListStatusEnum.php
Normal file
38
app/Enums/MangaListStatusEnum.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
|
||||
use Spatie\Enum\Laravel\Enum;
|
||||
|
||||
/**
|
||||
* @method static self all()
|
||||
* @method static self reading()
|
||||
* @method static self completed()
|
||||
* @method static self onhold()
|
||||
* @method static self dropped()
|
||||
* @method static self plantoread()
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="user_manga_list_status_filter",
|
||||
* description="User's anime list status filter options",
|
||||
* type="string",
|
||||
* enum={"all", "reading", "completed", "onhold", "dropped", "plantoread"}
|
||||
* )
|
||||
*/
|
||||
final class MangaListStatusEnum extends Enum
|
||||
{
|
||||
// labels will be the values used for mapping, meanwhile the values are the names of the enum elements,
|
||||
// because these are getting passed in through the query string in requests, and we validate against them
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
"all" => "7",
|
||||
"reading" => "1",
|
||||
"completed" => "2",
|
||||
"onhold" => "3",
|
||||
"dropped" => "4",
|
||||
"plantoread" => "6"
|
||||
];
|
||||
}
|
||||
}
|
47
app/Enums/UserAnimeListOrderByEnum.php
Normal file
47
app/Enums/UserAnimeListOrderByEnum.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
|
||||
use Spatie\Enum\Laravel\Enum;
|
||||
use Jikan\Helper\Constants as JikanConstants;
|
||||
|
||||
/**
|
||||
* @method static self title()
|
||||
* @method static self started_date()
|
||||
* @method static self score()
|
||||
* @method static self last_updated()
|
||||
* @method static self type()
|
||||
* @method static self rated()
|
||||
* @method static self rewatch_value()
|
||||
* @method static self priority()
|
||||
* @method static self episodes_watched()
|
||||
* @method static self storage()
|
||||
* @method static self air_start()
|
||||
* @method static self air_end()
|
||||
* @method static self status()
|
||||
*/
|
||||
final class UserAnimeListOrderByEnum extends Enum
|
||||
{
|
||||
// labels will be the values used for mapping, meanwhile the values are the names of the enum elements,
|
||||
// because these are getting passed in through the query string in requests, and we validate against them
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'title' => JikanConstants::USER_ANIME_LIST_ORDER_BY_TITLE,
|
||||
'finished_date' => JikanConstants::USER_ANIME_LIST_ORDER_BY_FINISHED_DATE,
|
||||
'started_date' => JikanConstants::USER_ANIME_LIST_ORDER_BY_STARTED_DATE,
|
||||
'score' => JikanConstants::USER_ANIME_LIST_ORDER_BY_SCORE,
|
||||
'last_updated' => JikanConstants::USER_ANIME_LIST_ORDER_BY_LAST_UPDATED,
|
||||
'type' => JikanConstants::USER_ANIME_LIST_ORDER_BY_TYPE,
|
||||
'rated' => JikanConstants::USER_ANIME_LIST_ORDER_BY_RATED,
|
||||
'rewatch_value' => JikanConstants::USER_ANIME_LIST_ORDER_BY_REWATCH_VALUE,
|
||||
'priority' => JikanConstants::USER_ANIME_LIST_ORDER_BY_PRIORITY,
|
||||
'episodes_watched' => JikanConstants::USER_ANIME_LIST_ORDER_BY_PROGRESS,
|
||||
'storage' => JikanConstants::USER_ANIME_LIST_ORDER_BY_STORAGE,
|
||||
'air_start' => JikanConstants::USER_ANIME_LIST_ORDER_BY_AIR_START,
|
||||
'air_end' => JikanConstants::USER_ANIME_LIST_ORDER_BY_AIR_END,
|
||||
'status' => JikanConstants::USER_ANIME_LIST_ORDER_BY_STATUS,
|
||||
];
|
||||
}
|
||||
}
|
14
app/Enums/UserListTypeEnum.php
Normal file
14
app/Enums/UserListTypeEnum.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 UserListTypeEnum extends Enum
|
||||
{
|
||||
}
|
45
app/Enums/UserMangaListOrderByEnum.php
Normal file
45
app/Enums/UserMangaListOrderByEnum.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
|
||||
use Spatie\Enum\Laravel\Enum;
|
||||
use Jikan\Helper\Constants as JikanConstants;
|
||||
|
||||
/**
|
||||
* @method static self title()
|
||||
* @method static self started_date()
|
||||
* @method static self score()
|
||||
* @method static self last_updated()
|
||||
* @method static self priority()
|
||||
* @method static self progress()
|
||||
* @method static self chapters_read()
|
||||
* @method static self volumes_read()
|
||||
* @method static self type()
|
||||
* @method static self publish_start()
|
||||
* @method static self publish_end()
|
||||
* @method static self status()
|
||||
*/
|
||||
final class UserMangaListOrderByEnum extends Enum
|
||||
{
|
||||
// labels will be the values used for mapping, meanwhile the values are the names of the enum elements,
|
||||
// because these are getting passed in through the query string in requests, and we validate against them
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'title' => JikanConstants::USER_MANGA_LIST_ORDER_BY_TITLE,
|
||||
'finished_date' => JikanConstants::USER_MANGA_LIST_ORDER_BY_FINISHED_DATE,
|
||||
'started_date' => JikanConstants::USER_MANGA_LIST_ORDER_BY_STARTED_DATE,
|
||||
'score' => JikanConstants::USER_MANGA_LIST_ORDER_BY_SCORE,
|
||||
'last_updated' => JikanConstants::USER_MANGA_LIST_ORDER_BY_LAST_UPDATED,
|
||||
'priority' => JikanConstants::USER_MANGA_LIST_ORDER_BY_PRIORITY,
|
||||
'progress' => JikanConstants::USER_MANGA_LIST_ORDER_BY_CHAPTERS,
|
||||
'chapters_read' => JikanConstants::USER_MANGA_LIST_ORDER_BY_CHAPTERS,
|
||||
'volumes_read' => JikanConstants::USER_MANGA_LIST_ORDER_BY_VOLUMES,
|
||||
'type' => JikanConstants::USER_MANGA_LIST_ORDER_BY_TYPE,
|
||||
'publish_start' => JikanConstants::USER_MANGA_LIST_ORDER_BY_PUBLISH_START,
|
||||
'publish_end' => JikanConstants::USER_MANGA_LIST_ORDER_BY_PUBLISH_END,
|
||||
'status' => JikanConstants::USER_MANGA_LIST_ORDER_BY_STATUS,
|
||||
];
|
||||
}
|
||||
}
|
34
app/Enums/UserMangaListStatusFilterEnum.php
Normal file
34
app/Enums/UserMangaListStatusFilterEnum.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
|
||||
use Spatie\Enum\Laravel\Enum;
|
||||
use Jikan\Helper\Constants as JikanConstants;
|
||||
|
||||
/**
|
||||
* @method static self publishing()
|
||||
* @method static self finished()
|
||||
* @method static self complete()
|
||||
* @method static self to_be_published()
|
||||
* @method static self not_yet_published()
|
||||
* @method static self tba()
|
||||
* @method static self nya()
|
||||
*/
|
||||
final class UserMangaListStatusFilterEnum extends Enum
|
||||
{
|
||||
// labels will be the values used for mapping, meanwhile the values are the names of the enum elements,
|
||||
// because these are getting passed in through the query string in requests, and we validate against them
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'airing' => JikanConstants::USER_ANIME_LIST_CURRENTLY_AIRING,
|
||||
'finished' => JikanConstants::USER_ANIME_LIST_FINISHED_AIRING,
|
||||
'complete' => JikanConstants::USER_ANIME_LIST_FINISHED_AIRING,
|
||||
'to_be_aired' => JikanConstants::USER_ANIME_LIST_NOT_YET_AIRED,
|
||||
'not_yet_aired' => JikanConstants::USER_ANIME_LIST_NOT_YET_AIRED,
|
||||
'tba' => JikanConstants::USER_ANIME_LIST_NOT_YET_AIRED,
|
||||
'nya' => JikanConstants::USER_ANIME_LIST_NOT_YET_AIRED,
|
||||
];
|
||||
}
|
||||
}
|
66
app/Features/QueryAnimeListOfUserHandler.php
Normal file
66
app/Features/QueryAnimeListOfUserHandler.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Features;
|
||||
|
||||
use App\Dto\QueryAnimeListOfUserCommand;
|
||||
use App\Http\Resources\V4\UserProfileAnimeListCollection;
|
||||
use App\Http\Resources\V4\UserProfileAnimeListResource;
|
||||
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\User\UserAnimeListRequest;
|
||||
|
||||
/**
|
||||
* @extends RequestHandlerWithScraperCache<QueryAnimeListOfUserCommand, JsonResponse>
|
||||
*/
|
||||
final class QueryAnimeListOfUserHandler extends RequestHandlerWithScraperCache
|
||||
{
|
||||
/**
|
||||
* @param QueryAnimeListOfUserCommand $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function handle($request)
|
||||
{
|
||||
$requestParams = collect(["jikanParserRequest" => $request->toJikanParserRequest()]);
|
||||
$requestFingerPrint = $request->getFingerPrint();
|
||||
$results = $this->getScraperData($requestFingerPrint, $requestParams);
|
||||
|
||||
return $this->renderResponse($requestFingerPrint, $results);
|
||||
}
|
||||
|
||||
public function resource(Collection $results): JsonResource
|
||||
{
|
||||
if ($results->isEmpty() || count($results->get("anime")) === 0) {
|
||||
return new UserProfileAnimeListCollection([]);
|
||||
}
|
||||
|
||||
$listResults = $results->get("anime");
|
||||
foreach ($listResults as &$result) {
|
||||
$result = (new UserProfileAnimeListResource($result));
|
||||
}
|
||||
|
||||
return new UserProfileAnimeListCollection($listResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function requestClass(): string
|
||||
{
|
||||
return QueryAnimeListOfUserCommand::class;
|
||||
}
|
||||
|
||||
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
|
||||
{
|
||||
/**
|
||||
* @var UserAnimeListRequest $jikanParserRequest
|
||||
*/
|
||||
$jikanParserRequest = $requestParams->get("jikanParserRequest");
|
||||
return $this->scraperService->findList(
|
||||
$requestFingerPrint,
|
||||
fn(MalClient $jikan, ?int $page = null) => ["anime" => $jikan->getUserAnimeList($jikanParserRequest)]
|
||||
);
|
||||
}
|
||||
}
|
66
app/Features/QueryMangaListOfUserHandler.php
Normal file
66
app/Features/QueryMangaListOfUserHandler.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Features;
|
||||
|
||||
use App\Dto\QueryMangaListOfUserCommand;
|
||||
use App\Http\Resources\V4\UserProfileAnimeListCollection;
|
||||
use App\Http\Resources\V4\UserProfileMangaListCollection;
|
||||
use App\Http\Resources\V4\UserProfileMangaListResource;
|
||||
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\User\UserMangaListRequest;
|
||||
|
||||
/**
|
||||
* @extends RequestHandlerWithScraperCache<QueryMangaListOfUserCommand, JsonResponse>
|
||||
*/
|
||||
final class QueryMangaListOfUserHandler extends RequestHandlerWithScraperCache
|
||||
{
|
||||
/**
|
||||
* @param QueryMangaListOfUserCommand $request
|
||||
*/
|
||||
public function handle($request)
|
||||
{
|
||||
$requestParams = collect(["jikanParserRequest" => $request->toJikanParserRequest()]);
|
||||
$requestFingerPrint = $request->getFingerPrint();
|
||||
$results = $this->getScraperData($requestFingerPrint, $requestParams);
|
||||
|
||||
return $this->renderResponse($requestFingerPrint, $results);
|
||||
}
|
||||
|
||||
public function resource(Collection $results): JsonResource
|
||||
{
|
||||
if ($results->isEmpty()) {
|
||||
return new UserProfileAnimeListCollection([]);
|
||||
}
|
||||
|
||||
$listResults = $results->first()['manga'];
|
||||
foreach ($listResults as &$result) {
|
||||
$result = (new UserProfileMangaListResource($result));
|
||||
}
|
||||
|
||||
return new UserProfileMangaListCollection($listResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function requestClass(): string
|
||||
{
|
||||
return QueryMangaListOfUserCommand::class;
|
||||
}
|
||||
|
||||
protected function getScraperData(string $requestFingerPrint, Collection $requestParams): CachedData
|
||||
{
|
||||
/**
|
||||
* @var UserMangaListRequest $jikanParserRequest
|
||||
*/
|
||||
$jikanParserRequest = $requestParams->get("jikanParserRequest");
|
||||
return $this->scraperService->findList(
|
||||
$requestFingerPrint,
|
||||
fn(MalClient $jikan, ?int $page = null) => ["anime" => $jikan->getUserMangaList($jikanParserRequest)]
|
||||
);
|
||||
}
|
||||
}
|
@ -2,7 +2,9 @@
|
||||
|
||||
namespace App\Http\Controllers\V4DB;
|
||||
|
||||
use App\Dto\QueryMangaListOfUserCommand;
|
||||
use App\Dto\QueryRecentlyOnlineUsersCommand;
|
||||
use App\Dto\QueryAnimeListOfUserCommand;
|
||||
use App\Dto\UserAboutLookupCommand;
|
||||
use App\Dto\UserClubsLookupCommand;
|
||||
use App\Dto\UserExternalLookupCommand;
|
||||
@ -349,6 +351,12 @@ class UserController extends Controller
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="status",
|
||||
* in="query",
|
||||
* @OA\Schema(ref="#/components/schemas/user_anime_list_status_filter")
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Returns user anime list",
|
||||
@ -362,10 +370,9 @@ class UserController extends Controller
|
||||
* ),
|
||||
*
|
||||
*/
|
||||
public function animelist(Request $request, string $username, ?string $status = null)
|
||||
public function animelist(QueryAnimeListOfUserCommand $command)
|
||||
{
|
||||
// noop, intentionally left blank
|
||||
// todo: remove as this is obsolete
|
||||
return $this->mediator->send($command);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -383,6 +390,12 @@ class UserController extends Controller
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="status",
|
||||
* in="query",
|
||||
* @OA\Schema(ref="#/components/schemas/user_manga_list_status_filter")
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Returns user manga list",
|
||||
@ -396,10 +409,9 @@ class UserController extends Controller
|
||||
* ),
|
||||
*
|
||||
*/
|
||||
public function mangalist(Request $request, string $username, ?string $status = null)
|
||||
public function mangalist(QueryMangaListOfUserCommand $command)
|
||||
{
|
||||
// noop, intentionally left blank
|
||||
// todo: remove as this is obsolete
|
||||
return $this->mediator->send($command);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,11 +31,13 @@ use App\Repositories\DefaultUserRepository;
|
||||
use App\Repositories\MangaGenresRepository;
|
||||
use App\Services\DefaultBuilderPaginatorService;
|
||||
use App\Services\DefaultCachedScraperService;
|
||||
use App\Services\DefaultPrivateFieldMapperService;
|
||||
use App\Services\DefaultQueryBuilderService;
|
||||
use App\Services\DefaultScoutSearchService;
|
||||
use App\Services\ElasticScoutSearchService;
|
||||
use App\Services\EloquentBuilderPaginatorService;
|
||||
use App\Services\MongoSearchService;
|
||||
use App\Services\PrivateFieldMapperService;
|
||||
use App\Services\QueryBuilderPaginatorService;
|
||||
use App\Services\ScoutBuilderPaginatorService;
|
||||
use App\Services\ScoutSearchService;
|
||||
@ -82,6 +84,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
// 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(PrivateFieldMapperService::class, DefaultPrivateFieldMapperService::class);
|
||||
$this->app->bind(QueryBuilderPaginatorService::class, DefaultBuilderPaginatorService::class);
|
||||
$this->registerModelRepositories();
|
||||
$this->registerRequestHandlers();
|
||||
@ -276,7 +279,9 @@ class AppServiceProvider extends ServiceProvider
|
||||
Features\QueryRecentlyAddedEpisodesHandler::class => $unitOfWorkInstance->documents("watch"),
|
||||
Features\QueryPopularEpisodesHandler::class => $unitOfWorkInstance->documents("watch"),
|
||||
Features\QueryRecentlyAddedPromoVideosHandler::class => $unitOfWorkInstance->documents("watch"),
|
||||
Features\QueryPopularPromoVideosHandler::class => $unitOfWorkInstance->documents("watch")
|
||||
Features\QueryPopularPromoVideosHandler::class => $unitOfWorkInstance->documents("watch"),
|
||||
Features\QueryAnimeListOfUserHandler::class => $unitOfWorkInstance->documents("users_animelist"),
|
||||
Features\QueryMangaListOfUserHandler::class => $unitOfWorkInstance->documents("users_mangalist")
|
||||
];
|
||||
|
||||
foreach ($requestHandlersWithScraperService as $handlerClass => $repositoryInstance) {
|
||||
@ -335,14 +340,6 @@ class AppServiceProvider extends ServiceProvider
|
||||
];
|
||||
}
|
||||
|
||||
private function getQueryBuilderFactory($queryBuilderClass): \Closure
|
||||
{
|
||||
return function($app) use($queryBuilderClass) {
|
||||
$searchIndexesEnabled = $this->getSearchIndexesEnabledConfig($app);
|
||||
return new $queryBuilderClass($searchIndexesEnabled, $app->make(ScoutSearchService::class));
|
||||
};
|
||||
}
|
||||
|
||||
private function getSearchIndexesEnabledConfig($app): bool
|
||||
{
|
||||
return $this->getSearchIndexDriver($app) != "null";
|
||||
|
34
app/Services/DefaultPrivateFieldMapperService.php
Normal file
34
app/Services/DefaultPrivateFieldMapperService.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Spatie\Enum\Laravel\Enum;
|
||||
use Spatie\LaravelData\Optional;
|
||||
|
||||
final class DefaultPrivateFieldMapperService implements PrivateFieldMapperService
|
||||
{
|
||||
public function map($instance, array $values): mixed
|
||||
{
|
||||
$cls = get_class($instance);
|
||||
|
||||
foreach ($values as $fieldName => $fieldValue) {
|
||||
if ($fieldValue instanceof Optional) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($fieldValue instanceof Enum) {
|
||||
$fieldValue = $fieldValue->label;
|
||||
}
|
||||
|
||||
if (!property_exists($cls, $fieldName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$reflection = new \ReflectionProperty($cls, $fieldName);
|
||||
// note: ->setAccessible call would be required under php version 8.1
|
||||
$reflection->setValue($instance, $fieldValue);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
}
|
58
app/Services/JikanUserListRequestMapperService.php
Normal file
58
app/Services/JikanUserListRequestMapperService.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Dto\QueryListOfUserCommand;
|
||||
use App\Enums\UserListTypeEnum;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Jikan\Request\User\UserAnimeListRequest;
|
||||
use Jikan\Request\User\UserMangaListRequest;
|
||||
use Spatie\LaravelData\Optional;
|
||||
|
||||
final class JikanUserListRequestMapperService
|
||||
{
|
||||
public function __construct(private readonly PrivateFieldMapperService $fieldMapperService)
|
||||
{
|
||||
}
|
||||
|
||||
public function map(QueryListOfUserCommand $command, UserListTypeEnum $listType): UserAnimeListRequest|UserMangaListRequest
|
||||
{
|
||||
$values = collect($command->all())->except(["username", "page", "status"])->toArray();
|
||||
|
||||
$status = $command->status;
|
||||
if ($status instanceof Optional) {
|
||||
$status = 7;
|
||||
}
|
||||
|
||||
if (array_key_exists("sort", $values)) {
|
||||
$values["sort"] = $values["sort"] === "asc" ? -1 : 1;
|
||||
}
|
||||
|
||||
if (!array_key_exists("page", $values)) {
|
||||
$values["page"] = 1;
|
||||
}
|
||||
|
||||
if ($listType->equals(UserListTypeEnum::anime())) {
|
||||
$rangeFrom = "airedFrom";
|
||||
$rangeTo = "airedTo";
|
||||
$jikanUserListRequest = new UserAnimeListRequest($command->username, $command->page, $status);
|
||||
}
|
||||
else {
|
||||
$rangeFrom = "publishedFrom";
|
||||
$rangeTo = "publishedTo";
|
||||
$jikanUserListRequest = new UserMangaListRequest($command->username, $command->page, $status);
|
||||
}
|
||||
|
||||
foreach ([$rangeFrom, $rangeTo] as $rangeField) {
|
||||
if (array_key_exists($rangeField, $values)) {
|
||||
/**
|
||||
* @var CarbonImmutable $c
|
||||
*/
|
||||
$c = $values[$rangeField];
|
||||
$values[$rangeField] = [$c->year, $c->month, $c->day];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->fieldMapperService->map($jikanUserListRequest, $values);
|
||||
}
|
||||
}
|
@ -14,8 +14,7 @@ final class MongoSearchService extends SearchServiceBase
|
||||
$query = $this->query();
|
||||
|
||||
/** @noinspection PhpParamsInspection */
|
||||
/** @noinspection PhpIncompatibleReturnTypeInspection */
|
||||
return $query->whereRaw([
|
||||
$builder = $query->whereRaw([
|
||||
'$text' => [
|
||||
'$search' => $searchTerms
|
||||
],
|
||||
@ -24,5 +23,14 @@ final class MongoSearchService extends SearchServiceBase
|
||||
'$meta' => 'textScore'
|
||||
]
|
||||
])->orderBy('textMatchScore', 'desc');
|
||||
|
||||
if ($orderByFields !== null) {
|
||||
$order = explode(",", $orderByFields);
|
||||
foreach ($order as $o) {
|
||||
$builder = $builder->orderBy($o, $sortDirectionDescending ? 'desc' : 'asc');
|
||||
}
|
||||
}
|
||||
|
||||
return $builder;
|
||||
}
|
||||
}
|
||||
|
8
app/Services/PrivateFieldMapperService.php
Normal file
8
app/Services/PrivateFieldMapperService.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
interface PrivateFieldMapperService
|
||||
{
|
||||
public function map($instance, array $values): mixed;
|
||||
}
|
@ -3,8 +3,12 @@
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Club;
|
||||
use App\Enums\ClubCategoryEnum;
|
||||
use App\Enums\ClubOrderByEnum;
|
||||
use App\Enums\ClubTypeEnum;
|
||||
use App\Testing\JikanDataGenerator;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use MongoDB\BSON\UTCDateTime;
|
||||
|
||||
final class ClubFactory extends JikanModelFactory
|
||||
@ -77,4 +81,98 @@ final class ClubFactory extends JikanModelFactory
|
||||
"access" => $this->faker->randomElement(["public", "private"])
|
||||
];
|
||||
}
|
||||
|
||||
public function overrideFromQueryStringParameters(array $additionalParams, bool $doOpposite = false): self
|
||||
{
|
||||
$additionalParams = collect($additionalParams);
|
||||
|
||||
if ($doOpposite) {
|
||||
$overrides = $this->getOppositeOverridesFromQueryStringParameters($additionalParams);
|
||||
}
|
||||
else {
|
||||
$overrides = $this->getOverridesFromQueryStringParameters($additionalParams);
|
||||
}
|
||||
|
||||
return $this->state($this->serializeStateDefinition($overrides));
|
||||
}
|
||||
|
||||
protected function getOverridesFromQueryStringParameters(Collection $additionalParams): array
|
||||
{
|
||||
$overrides = [];
|
||||
|
||||
if ($additionalParams->has("type")) {
|
||||
$typeOverride = collect(ClubTypeEnum::toArray())->get(strtolower($additionalParams["type"]));
|
||||
if (!is_null($typeOverride)) {
|
||||
$overrides["type"] = $typeOverride;
|
||||
}
|
||||
}
|
||||
|
||||
if ($additionalParams->has("letter")) {
|
||||
$overrides["name"] = $additionalParams["letter"] . $this->createTitle();
|
||||
}
|
||||
|
||||
if ($additionalParams->has("category")) {
|
||||
$categoryOverride = collect(ClubCategoryEnum::toArray())->get(strtolower($additionalParams["category"]));
|
||||
if (!is_null($categoryOverride)) {
|
||||
$overrides["category"] = $categoryOverride;
|
||||
}
|
||||
}
|
||||
|
||||
return $overrides;
|
||||
}
|
||||
|
||||
protected function getOppositeOverridesFromQueryStringParameters(Collection $additionalParams): array
|
||||
{
|
||||
$overrides = [];
|
||||
|
||||
if ($additionalParams->has("type")) {
|
||||
// value => label key pairs
|
||||
// we store labels in the database
|
||||
$types = ClubTypeEnum::toArray();
|
||||
$typeKey = $this->faker->randomElement(array_diff(array_keys($types), [$additionalParams["type"]]));
|
||||
$overrides["type"] = $types[$typeKey];
|
||||
}
|
||||
|
||||
if ($additionalParams->has("letter")) {
|
||||
$alphabet = array_filter(range("a", "z"), fn ($elem) => $elem !== $additionalParams["letter"]);
|
||||
$overrides["name"] = $this->faker->randomElement($alphabet) . $this->createTitle();
|
||||
}
|
||||
|
||||
if ($additionalParams->has("category")) {
|
||||
$categories = ClubCategoryEnum::toArray();
|
||||
$categoryKey = $this->faker->randomElement(array_diff(array_keys($categories), [$additionalParams["category"]]));
|
||||
$overrides["category"] = $categories[$categoryKey];
|
||||
}
|
||||
|
||||
return $overrides;
|
||||
}
|
||||
|
||||
public function createManyWithOrder(string $orderByField): Collection
|
||||
{
|
||||
$count = $this->count ?? 3;
|
||||
$items = collect();
|
||||
|
||||
$fieldValueGenerator = match($orderByField) {
|
||||
ClubOrderByEnum::name()->value => ((function() {
|
||||
$alphabet = range("a", "z");
|
||||
$alphabetCount = count($alphabet);
|
||||
return fn($i) => $alphabet[$i % $alphabetCount];
|
||||
})()),
|
||||
ClubOrderByEnum::created()->value => ((function() {
|
||||
$randomDate = $this->createRandomDateTime("-5 years");
|
||||
return fn($i) => new UTCDateTime($randomDate->copy()->addDays($i)->getPreciseTimestamp(3));
|
||||
})()),
|
||||
default => fn($i) => $i,
|
||||
};
|
||||
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
$createdItem = $this->createOne([
|
||||
$orderByField => $fieldValueGenerator($i)
|
||||
]);
|
||||
|
||||
$items->add($createdItem);
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
|
@ -133,6 +133,8 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
|
||||
$activityMarkerKeyName = $this->descriptor->activityMarkerKeyName();
|
||||
// let's make all database items the same type
|
||||
if ($additionalParams->has("type")) {
|
||||
// value => label key pairs
|
||||
// we store labels in the database
|
||||
$typeOverride = collect($this->descriptor->typeParamMap())->get(strtolower($additionalParams["type"]));
|
||||
if (!is_null($typeOverride)) {
|
||||
$overrides["type"] = $typeOverride;
|
||||
@ -256,8 +258,11 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
|
||||
$activityMarkerKeyName = $this->descriptor->activityMarkerKeyName();
|
||||
|
||||
if ($additionalParams->has("type")) {
|
||||
// value => label key pairs
|
||||
// we store labels in the database
|
||||
$types = $this->descriptor->typeParamMap();
|
||||
$overrides["type"] = $this->faker->randomElement(array_diff(array_keys($types), [$additionalParams["type"]]));
|
||||
$typeKey = $this->faker->randomElement(array_diff(array_keys($types), [$additionalParams["type"]]));
|
||||
$overrides["type"] = $types[$typeKey];
|
||||
}
|
||||
|
||||
if ($additionalParams->has("letter")) {
|
||||
|
@ -7,7 +7,7 @@ require_once __DIR__.'/vendor/autoload.php';
|
||||
|
||||
$safe_defaults = [
|
||||
// mongodb regex search by default
|
||||
"SCOUT_DRIVER" => "null",
|
||||
"SCOUT_DRIVER" => "none",
|
||||
"SCOUT_QUEUE" => false,
|
||||
"THROTTLE" => false,
|
||||
"QUEUE_CONNECTION" => "database",
|
||||
|
@ -44,12 +44,22 @@ class AnimeSearchEndpointTest extends TestCase
|
||||
public function limitParameterCombinationsProvider(): array
|
||||
{
|
||||
return [
|
||||
[5, []],
|
||||
[5, ["type" => "tv"]],
|
||||
[5, ["type" => "tv", "min_score" => 7]],
|
||||
[5, ["type" => "tv", "max_score" => 6]],
|
||||
[5, ["type" => "tv", "status" => "complete", "max_score" => 8]],
|
||||
[5, ["type" => "movie", "status" => "complete", "max_score" => 8]]
|
||||
"query string = `?limit=5`" => [
|
||||
[5, []]
|
||||
],
|
||||
"query string = `?limit=5&type=tv`" => [5, ["type" => "tv"]],
|
||||
"query string = `?limit=5&type=tv&min_score=7`" => [
|
||||
5, ["type" => "tv", "min_score" => 7]
|
||||
],
|
||||
"query string = `?limit=5&type=tv&max_score=6`" => [
|
||||
5, ["type" => "tv", "max_score" => 6]
|
||||
],
|
||||
"query string = `?limit=5&type=tv&status=complete&max_score=8`" => [
|
||||
5, ["type" => "tv", "status" => "complete", "max_score" => 8]
|
||||
],
|
||||
"query string = `?limit=5&type=movie&status=complete&max_score=8`" => [
|
||||
5, ["type" => "movie", "status" => "complete", "max_score" => 8]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -46,12 +46,16 @@ class MangaSearchEndpointTest extends TestCase
|
||||
public function limitParameterCombinationsProvider(): array
|
||||
{
|
||||
return [
|
||||
[5, []],
|
||||
[5, ["type" => "manga"]],
|
||||
[5, ["type" => "novel", "min_score" => 7]],
|
||||
[5, ["type" => "manga", "max_score" => 6]],
|
||||
[5, ["type" => "manga", "status" => "complete", "max_score" => 8]],
|
||||
[5, ["type" => "oneshot", "status" => "complete", "max_score" => 8]]
|
||||
"query string = `?limit=5`" => [5, []],
|
||||
"query string = `?limit=5&type=manga`" =>[5, ["type" => "manga"]],
|
||||
"query string = `?limit=5&type=novel&min_score=7`" => [5, ["type" => "novel", "min_score" => 7]],
|
||||
"query string = `?limit=5&type=manga&max_score=6`" => [5, ["type" => "manga", "max_score" => 6]],
|
||||
"query string = `?limit=5&type=manga&status=complete&max_score=8`" => [
|
||||
5, ["type" => "manga", "status" => "complete", "max_score" => 8]
|
||||
],
|
||||
"query string = `?limit=5&type=oneshot&status=complete&max_score=8`" => [
|
||||
5, ["type" => "oneshot", "status" => "complete", "max_score" => 8]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ final class DefaultCachedScraperServiceTest extends TestCase
|
||||
["dummy" => "dummy1"],
|
||||
["dummy" => "dummy2"]
|
||||
]
|
||||
]]);;
|
||||
]]);
|
||||
|
||||
[$queryBuilderMock, $repositoryMock, $serializerMock] = $this->makeCtorArgMocks(2);
|
||||
$repositoryMock->expects()->insert(Mockery::capture($insertedData))->once()->andReturn(true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user