mirror of
https://github.com/jikan-me/jikan-rest.git
synced 2025-02-20 11:23:35 +08:00
Merge pull request #527 from jikan-me/bugfix/continuing-items-in-season
✅ Fixed a bug around season endpoints
This commit is contained in:
commit
9470beb14b
@ -39,11 +39,12 @@ interface AnimeRepository extends Repository
|
|||||||
?AnimeScheduleFilterEnum $filter = null
|
?AnimeScheduleFilterEnum $filter = null
|
||||||
): EloquentBuilder;
|
): EloquentBuilder;
|
||||||
|
|
||||||
public function getAiredBetween(
|
public function getItemsBySeason(
|
||||||
Carbon $from,
|
Carbon $from,
|
||||||
Carbon $to,
|
Carbon $to,
|
||||||
?AnimeTypeEnum $type = null,
|
?AnimeTypeEnum $type = null,
|
||||||
?string $premiered = null
|
?string $premiered = null,
|
||||||
|
bool $includeContinuingItems = false
|
||||||
): EloquentBuilder;
|
): EloquentBuilder;
|
||||||
|
|
||||||
public function getUpcomingSeasonItems(?AnimeTypeEnum $type = null): EloquentBuilder;
|
public function getUpcomingSeasonItems(?AnimeTypeEnum $type = null): EloquentBuilder;
|
||||||
|
26
app/Dto/Concerns/HasContinuingParameter.php
Normal file
26
app/Dto/Concerns/HasContinuingParameter.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto\Concerns;
|
||||||
|
|
||||||
|
use App\Casts\ContextualBooleanCast;
|
||||||
|
use OpenApi\Annotations as OA;
|
||||||
|
use Spatie\LaravelData\Attributes\Validation\BooleanType;
|
||||||
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
|
use Spatie\LaravelData\Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OA\Parameter(
|
||||||
|
* name="continuing",
|
||||||
|
* in="query",
|
||||||
|
* required=false,
|
||||||
|
* description="This is a flag. When supplied it will include entries which are continuing from previous seasons. MAL includes these items on the seasons view in the ″TV (continuing)″ section. (Example: https://myanimelist.net/anime/season/2024/winter) <br />Example usage: `?continuing`",
|
||||||
|
* @OA\Schema(type="boolean")
|
||||||
|
* ),
|
||||||
|
*/
|
||||||
|
trait HasContinuingParameter
|
||||||
|
{
|
||||||
|
use PreparesData;
|
||||||
|
|
||||||
|
#[BooleanType, WithCast(ContextualBooleanCast::class)]
|
||||||
|
public bool|Optional $continuing = false;
|
||||||
|
}
|
@ -17,7 +17,6 @@ trait PreparesData
|
|||||||
{
|
{
|
||||||
// let's always set the limit parameter to the globally configured default value
|
// let's always set the limit parameter to the globally configured default value
|
||||||
if (property_exists(static::class, "limit") && !$properties->has("limit")) {
|
if (property_exists(static::class, "limit") && !$properties->has("limit")) {
|
||||||
/** @noinspection PhpUndefinedFieldInspection */
|
|
||||||
$properties->put("limit", max_results_per_page(
|
$properties->put("limit", max_results_per_page(
|
||||||
property_exists(static::class, "defaultLimit") ? static::$defaultLimit : null));
|
property_exists(static::class, "defaultLimit") ? static::$defaultLimit : null));
|
||||||
}
|
}
|
||||||
@ -44,7 +43,7 @@ trait PreparesData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if the property is optional and the value is an empty string, we want to ignore it.
|
// if the property is optional and the value is an empty string, we want to ignore it.
|
||||||
if ($property->type->isOptional && $propertyVal === "") {
|
if ($property->type->isOptional && $propertyVal === "" && !$property->type->acceptsType("bool")) {
|
||||||
$propertyVal = null;
|
$propertyVal = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +52,7 @@ trait PreparesData
|
|||||||
} else {
|
} else {
|
||||||
$properties->forget($propertyRawName);
|
$properties->forget($propertyRawName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $properties;
|
return $properties;
|
||||||
|
@ -11,6 +11,7 @@ use App\Dto\Concerns\HasLimitParameter;
|
|||||||
use App\Dto\Concerns\HasPageParameter;
|
use App\Dto\Concerns\HasPageParameter;
|
||||||
use App\Dto\Concerns\HasSfwParameter;
|
use App\Dto\Concerns\HasSfwParameter;
|
||||||
use App\Dto\Concerns\HasUnapprovedParameter;
|
use App\Dto\Concerns\HasUnapprovedParameter;
|
||||||
|
use App\Dto\Concerns\HasContinuingParameter;
|
||||||
use App\Enums\AnimeTypeEnum;
|
use App\Enums\AnimeTypeEnum;
|
||||||
use App\Rules\Attributes\EnumValidation;
|
use App\Rules\Attributes\EnumValidation;
|
||||||
use Spatie\LaravelData\Attributes\WithCast;
|
use Spatie\LaravelData\Attributes\WithCast;
|
||||||
@ -20,7 +21,13 @@ use Spatie\LaravelData\Optional;
|
|||||||
|
|
||||||
abstract class QueryAnimeSeasonCommand extends Data implements DataRequest
|
abstract class QueryAnimeSeasonCommand extends Data implements DataRequest
|
||||||
{
|
{
|
||||||
use HasSfwParameter, HasKidsParameter, HasUnapprovedParameter, HasLimitParameter, HasRequestFingerprint, HasPageParameter;
|
use HasSfwParameter,
|
||||||
|
HasKidsParameter,
|
||||||
|
HasUnapprovedParameter,
|
||||||
|
HasLimitParameter,
|
||||||
|
HasRequestFingerprint,
|
||||||
|
HasPageParameter,
|
||||||
|
HasContinuingParameter;
|
||||||
|
|
||||||
#[WithCast(EnumCast::class, AnimeTypeEnum::class), EnumValidation(AnimeTypeEnum::class)]
|
#[WithCast(EnumCast::class, AnimeTypeEnum::class), EnumValidation(AnimeTypeEnum::class)]
|
||||||
public AnimeTypeEnum|Optional $filter;
|
public AnimeTypeEnum|Optional $filter;
|
||||||
|
@ -32,8 +32,6 @@ abstract class QueryAnimeSeasonHandlerBase implements RequestHandler
|
|||||||
{
|
{
|
||||||
$requestParams = collect($request->all());
|
$requestParams = collect($request->all());
|
||||||
$type = $requestParams->has("filter") ? $request->filter : null;
|
$type = $requestParams->has("filter") ? $request->filter : null;
|
||||||
$season = $requestParams->has("season") ? $request->season : null;
|
|
||||||
$year = $requestParams->has("year") ? $request->year : null;
|
|
||||||
$results = $this->getSeasonItems($request, $type);
|
$results = $this->getSeasonItems($request, $type);
|
||||||
// apply sfw, kids and unapproved filters
|
// apply sfw, kids and unapproved filters
|
||||||
/** @noinspection PhpUndefinedMethodInspection */
|
/** @noinspection PhpUndefinedMethodInspection */
|
||||||
|
@ -53,7 +53,8 @@ final class QueryCurrentAnimeSeasonHandler extends QueryAnimeSeasonHandlerBase
|
|||||||
*/
|
*/
|
||||||
[$from, $to] = $this->getSeasonRange($year, $season);
|
[$from, $to] = $this->getSeasonRange($year, $season);
|
||||||
$premiered = ucfirst($season)." {$year}";
|
$premiered = ucfirst($season)." {$year}";
|
||||||
|
$includeContinuingItems = $request->continuing;
|
||||||
|
|
||||||
return $this->repository->getAiredBetween($from, $to, $type, $premiered);
|
return $this->repository->getItemsBySeason($from, $to, $type, $premiered, $includeContinuingItems);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,8 @@ final class QuerySpecificAnimeSeasonHandler extends QueryAnimeSeasonHandlerBase
|
|||||||
|
|
||||||
[$from, $to] = $this->getSeasonRange($request->year, $request->season);
|
[$from, $to] = $this->getSeasonRange($request->year, $request->season);
|
||||||
$premiered = ucfirst($request->season)." {$request->year}";
|
$premiered = ucfirst($request->season)." {$request->year}";
|
||||||
|
$includeContinuingItems = $request->continuing;
|
||||||
|
|
||||||
return $this->repository->getAiredBetween($from, $to, $type, $premiered);
|
return $this->repository->getItemsBySeason($from, $to, $type, $premiered, $includeContinuingItems);
|
||||||
// ->where("status", "!=", AnimeStatusEnum::upcoming()->label);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\V4DB;
|
namespace App\Http\Controllers\V4DB;
|
||||||
|
|
||||||
use App\Anime;
|
|
||||||
use App\Dto\QueryAnimeSeasonListCommand;
|
use App\Dto\QueryAnimeSeasonListCommand;
|
||||||
use App\Dto\QueryCurrentAnimeSeasonCommand;
|
use App\Dto\QueryCurrentAnimeSeasonCommand;
|
||||||
use App\Dto\QuerySpecificAnimeSeasonCommand;
|
use App\Dto\QuerySpecificAnimeSeasonCommand;
|
||||||
use App\Dto\QueryUpcomingAnimeSeasonCommand;
|
use App\Dto\QueryUpcomingAnimeSeasonCommand;
|
||||||
use App\Http\HttpResponse;
|
|
||||||
use App\Http\QueryBuilder\AnimeSearchQueryBuilder;
|
|
||||||
use App\Http\Resources\V4\AnimeCollection;
|
|
||||||
use App\Http\Resources\V4\ResultsResource;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Http\Request;
|
use OpenApi\Annotations as OA;
|
||||||
use Illuminate\Support\Carbon;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Jikan\Request\SeasonList\SeasonListRequest;
|
|
||||||
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -38,6 +29,7 @@ class SeasonController extends Controller
|
|||||||
*
|
*
|
||||||
* @OA\Parameter(ref="#/components/parameters/sfw"),
|
* @OA\Parameter(ref="#/components/parameters/sfw"),
|
||||||
* @OA\Parameter(ref="#/components/parameters/unapproved"),
|
* @OA\Parameter(ref="#/components/parameters/unapproved"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/continuing"),
|
||||||
* @OA\Parameter(ref="#/components/parameters/page"),
|
* @OA\Parameter(ref="#/components/parameters/page"),
|
||||||
* @OA\Parameter(ref="#/components/parameters/limit"),
|
* @OA\Parameter(ref="#/components/parameters/limit"),
|
||||||
*
|
*
|
||||||
@ -89,6 +81,7 @@ class SeasonController extends Controller
|
|||||||
*
|
*
|
||||||
* @OA\Parameter(ref="#/components/parameters/sfw"),
|
* @OA\Parameter(ref="#/components/parameters/sfw"),
|
||||||
* @OA\Parameter(ref="#/components/parameters/unapproved"),
|
* @OA\Parameter(ref="#/components/parameters/unapproved"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/continuing"),
|
||||||
* @OA\Parameter(ref="#/components/parameters/page"),
|
* @OA\Parameter(ref="#/components/parameters/page"),
|
||||||
* @OA\Parameter(ref="#/components/parameters/limit"),
|
* @OA\Parameter(ref="#/components/parameters/limit"),
|
||||||
*
|
*
|
||||||
@ -177,6 +170,7 @@ class SeasonController extends Controller
|
|||||||
*
|
*
|
||||||
* @OA\Parameter(ref="#/components/parameters/sfw"),
|
* @OA\Parameter(ref="#/components/parameters/sfw"),
|
||||||
* @OA\Parameter(ref="#/components/parameters/unapproved"),
|
* @OA\Parameter(ref="#/components/parameters/unapproved"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/continuing"),
|
||||||
* @OA\Parameter(ref="#/components/parameters/page"),
|
* @OA\Parameter(ref="#/components/parameters/page"),
|
||||||
* @OA\Parameter(ref="#/components/parameters/limit"),
|
* @OA\Parameter(ref="#/components/parameters/limit"),
|
||||||
*
|
*
|
||||||
|
@ -12,6 +12,7 @@ use Illuminate\Contracts\Database\Query\Builder as EloquentBuilder;
|
|||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Laravel\Scout\Builder as ScoutBuilder;
|
use Laravel\Scout\Builder as ScoutBuilder;
|
||||||
|
use MongoDB\BSON\UTCDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements Repository<Anime>
|
* @implements Repository<Anime>
|
||||||
@ -110,11 +111,12 @@ final class DefaultAnimeRepository extends DatabaseRepository implements AnimeRe
|
|||||||
return $queryable;
|
return $queryable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAiredBetween(
|
public function getItemsBySeason(
|
||||||
Carbon $from,
|
Carbon $from,
|
||||||
Carbon $to,
|
Carbon $to,
|
||||||
?AnimeTypeEnum $type = null,
|
?AnimeTypeEnum $type = null,
|
||||||
?string $premiered = null
|
?string $premiered = null,
|
||||||
|
bool $includeContinuingItems = false
|
||||||
): EloquentBuilder
|
): EloquentBuilder
|
||||||
{
|
{
|
||||||
$queryable = $this->queryable(true);
|
$queryable = $this->queryable(true);
|
||||||
@ -127,9 +129,10 @@ final class DefaultAnimeRepository extends DatabaseRepository implements AnimeRe
|
|||||||
$finalFilter = [];
|
$finalFilter = [];
|
||||||
|
|
||||||
// if the premiered parameter for the filter is not null, look for those items which have a premiered attribute set,
|
// if the premiered parameter for the filter is not null, look for those items which have a premiered attribute set,
|
||||||
// and equals to the parameter value, OR look for those items which doesn't have premired attribute set,
|
// and equals to the parameter value, OR look for those items which doesn't have premiered attribute set,
|
||||||
// they don't have a garbled aired string and their aired.from date is within the from-to parameters range.
|
// they don't have a garbled aired string and their aired.from date is within the from-to parameters range.
|
||||||
// Additionally, we want to include all those items which are carry overs from previous seasons.
|
// Additionally, we want to include all those items which are carry overs from previous seasons,
|
||||||
|
// if the includeContinuingItems argument is set to true.
|
||||||
if ($premiered !== null) {
|
if ($premiered !== null) {
|
||||||
$finalFilter['$or'] = [
|
$finalFilter['$or'] = [
|
||||||
['premiered' => $premiered],
|
['premiered' => $premiered],
|
||||||
@ -140,12 +143,50 @@ final class DefaultAnimeRepository extends DatabaseRepository implements AnimeRe
|
|||||||
],
|
],
|
||||||
...$airedFilter
|
...$airedFilter
|
||||||
],
|
],
|
||||||
// this condition will include "continuing" items from previous seasons
|
|
||||||
[
|
|
||||||
'aired.from' => ['$lte' => $from->toAtomString()],
|
|
||||||
'airing' => true
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
|
if ($includeContinuingItems) {
|
||||||
|
// these conditions will include "continuing" items from previous seasons
|
||||||
|
// long running shows
|
||||||
|
$finalFilter['$or'][] = [
|
||||||
|
'aired.from' => ['$lte' => $from->toAtomString()],
|
||||||
|
'aired.to' => null,
|
||||||
|
'episodes' => null,
|
||||||
|
'airing' => true
|
||||||
|
];
|
||||||
|
// We want to include those which are currently airing, and their aired.to is past the date of the
|
||||||
|
// current season start.
|
||||||
|
$finalFilter['$or'][] = [
|
||||||
|
'aired.from' => ['$lte' => $from->toAtomString()],
|
||||||
|
'aired.to' => ['$gte' => $from->toAtomString()],
|
||||||
|
'airing' => true
|
||||||
|
];
|
||||||
|
// In many cases MAL doesn't show the date until an airing show is going to be aired. So we need to get
|
||||||
|
// clever here.
|
||||||
|
// We want to include those shows which have started in previous season only (not before) and it's going
|
||||||
|
// to continue in the current season.
|
||||||
|
$finalFilter['$or'][] = [
|
||||||
|
// note: this expression only works with mongodb version 5.0.0 or higher
|
||||||
|
'$expr' => [
|
||||||
|
'$lte' => [
|
||||||
|
[
|
||||||
|
'$dateDiff' => [
|
||||||
|
'startDate' => [
|
||||||
|
'$dateFromString' => [
|
||||||
|
'dateString' => '$aired.from'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'endDate' => new UTCDateTime($from),
|
||||||
|
'unit' => 'month'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
3 // there are 3 months in a season, so anything that started in 3 months or less will be included
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'aired.to' => null,
|
||||||
|
'episodes' => ['$gte' => 14],
|
||||||
|
'airing' => true
|
||||||
|
];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$finalFilter = array_merge($finalFilter, $airedFilter);
|
$finalFilter = array_merge($finalFilter, $airedFilter);
|
||||||
$finalFilter['aired.string'] = [
|
$finalFilter['aired.string'] = [
|
||||||
|
@ -32,6 +32,7 @@ trait SyntheticMongoDbTransaction
|
|||||||
$tablesWithoutModels = [
|
$tablesWithoutModels = [
|
||||||
"anime_characters_staff",
|
"anime_characters_staff",
|
||||||
"anime_episodes",
|
"anime_episodes",
|
||||||
|
"anime_episode",
|
||||||
"anime_forum",
|
"anime_forum",
|
||||||
"anime_moreinfo",
|
"anime_moreinfo",
|
||||||
"anime_news",
|
"anime_news",
|
||||||
@ -42,6 +43,7 @@ trait SyntheticMongoDbTransaction
|
|||||||
"anime_userupdates",
|
"anime_userupdates",
|
||||||
"anime_videos",
|
"anime_videos",
|
||||||
"character_pictures",
|
"character_pictures",
|
||||||
|
"characters_pictures",
|
||||||
"clubs_members",
|
"clubs_members",
|
||||||
"demographics_manga",
|
"demographics_manga",
|
||||||
"demographics_anime",
|
"demographics_anime",
|
||||||
|
@ -244,7 +244,7 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
|
|||||||
if ($additionalParams->has("start_date") && !empty($additionalParams["start_date"])
|
if ($additionalParams->has("start_date") && !empty($additionalParams["start_date"])
|
||||||
&& !$additionalParams->has("end_date")) {
|
&& !$additionalParams->has("end_date")) {
|
||||||
$startDate = $this->adaptDateString($additionalParams["start_date"]);
|
$startDate = $this->adaptDateString($additionalParams["start_date"]);
|
||||||
$dt = Carbon::parse($startDate)->addDays($this->faker->numberBetween(0, 25));
|
$dt = Carbon::parse($startDate)->addDays($this->faker->numberBetween(1, 25));
|
||||||
$overrides[$activityMarkerKeyName] = new CarbonDateRange($dt, null);
|
$overrides[$activityMarkerKeyName] = new CarbonDateRange($dt, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
|
|||||||
$endDate = $this->adaptDateString($additionalParams["end_date"]);
|
$endDate = $this->adaptDateString($additionalParams["end_date"]);
|
||||||
$to = Carbon::parse($endDate);
|
$to = Carbon::parse($endDate);
|
||||||
$from = $to->copy()->subDays($this->faker->randomElement([30, 60, 90, 120, 180]));
|
$from = $to->copy()->subDays($this->faker->randomElement([30, 60, 90, 120, 180]));
|
||||||
$overrides[$activityMarkerKeyName] = new CarbonDateRange($from, $to->subDays($this->faker->numberBetween(0, 25)));
|
$overrides[$activityMarkerKeyName] = new CarbonDateRange($from, $to->subDays($this->faker->numberBetween(1, 25)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($additionalParams->has(["start_date", "end_date"])
|
if ($additionalParams->has(["start_date", "end_date"])
|
||||||
@ -312,14 +312,14 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
|
|||||||
if ($additionalParams->has("min_score") && !$additionalParams->has("max_score")) {
|
if ($additionalParams->has("min_score") && !$additionalParams->has("max_score")) {
|
||||||
$min_score = floatval($additionalParams["min_score"]);
|
$min_score = floatval($additionalParams["min_score"]);
|
||||||
if ($this->isScoreValueValid($min_score)) {
|
if ($this->isScoreValueValid($min_score)) {
|
||||||
$overrides["score"] = $this->faker->randomFloat(2, 1.00, floatval($additionalParams["min_score"]));
|
$overrides["score"] = $this->faker->randomFloat(2, 1.00, floatval($additionalParams["min_score"]) - 0.01);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$additionalParams->has("min_score") && $additionalParams->has("max_score")) {
|
if (!$additionalParams->has("min_score") && $additionalParams->has("max_score")) {
|
||||||
$max_score = $additionalParams["max_score"];
|
$max_score = $additionalParams["max_score"];
|
||||||
if ($this->isScoreValueValid($max_score)) {
|
if ($this->isScoreValueValid($max_score)) {
|
||||||
$overrides["score"] = $this->faker->randomFloat(2, floatval($additionalParams["max_score"]), 9.99);
|
$overrides["score"] = $this->faker->randomFloat(2, floatval($additionalParams["max_score"]) + 0.01, 9.99);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,8 +330,8 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
|
|||||||
if ($this->isScoreValueValid($min_score) && $this->isScoreValueValid($max_score))
|
if ($this->isScoreValueValid($min_score) && $this->isScoreValueValid($max_score))
|
||||||
{
|
{
|
||||||
$overrides["score"] = $this->faker->randomElement([
|
$overrides["score"] = $this->faker->randomElement([
|
||||||
$this->faker->randomFloat(2, 1.00, floatval($additionalParams["min_score"])),
|
$this->faker->randomFloat(2, 1.00, floatval($additionalParams["min_score"]) - 0.01),
|
||||||
$this->faker->randomFloat(2, floatval($additionalParams["max_score"]), 9.99)
|
$this->faker->randomFloat(2, floatval($additionalParams["max_score"]) + 0.01, 9.99)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,18 @@ use Jikan\Model\Common\DateRange;
|
|||||||
use JMS\Serializer\Serializer;
|
use JMS\Serializer\Serializer;
|
||||||
use \Illuminate\Database\Eloquent\Factories\Factory;
|
use \Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
use Spatie\Enum\Laravel\Faker\FakerEnumProvider;
|
use Spatie\Enum\Laravel\Faker\FakerEnumProvider;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
abstract class JikanModelFactory extends Factory
|
abstract class JikanModelFactory extends Factory
|
||||||
{
|
{
|
||||||
public function configure(): JikanModelFactory|static
|
public function configure(): JikanModelFactory|static
|
||||||
{
|
{
|
||||||
$this->faker->addProvider(new FakerEnumProvider($this->faker));
|
$this->faker->addProvider(new FakerEnumProvider($this->faker));
|
||||||
|
if (array_key_exists("GITHUB_JOB", $_ENV) && $_ENV["GITHUB_JOB"] !== "") {
|
||||||
|
$this->faker->seed($_ENV["GITHUB_JOB"]);
|
||||||
|
} else {
|
||||||
|
$this->faker->seed(Str::random());
|
||||||
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3046,6 +3046,9 @@
|
|||||||
{
|
{
|
||||||
"$ref": "#/components/parameters/unapproved"
|
"$ref": "#/components/parameters/unapproved"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/continuing"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/components/parameters/page"
|
"$ref": "#/components/parameters/page"
|
||||||
},
|
},
|
||||||
@ -3115,6 +3118,9 @@
|
|||||||
{
|
{
|
||||||
"$ref": "#/components/parameters/unapproved"
|
"$ref": "#/components/parameters/unapproved"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/continuing"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/components/parameters/page"
|
"$ref": "#/components/parameters/page"
|
||||||
},
|
},
|
||||||
@ -3191,6 +3197,9 @@
|
|||||||
{
|
{
|
||||||
"$ref": "#/components/parameters/unapproved"
|
"$ref": "#/components/parameters/unapproved"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/continuing"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/components/parameters/page"
|
"$ref": "#/components/parameters/page"
|
||||||
},
|
},
|
||||||
@ -9027,6 +9036,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
"continuing": {
|
||||||
|
"name": "continuing",
|
||||||
|
"in": "query",
|
||||||
|
"description": "This is a flag. When supplied it will include entries which are continuing from previous seasons. MAL includes these items on the seasons view in the ″TV (continuing)″ section. (Example: https://myanimelist.net/anime/season/2024/winter) <br />Example usage: `?continuing`",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
"kids": {
|
"kids": {
|
||||||
"name": "kids",
|
"name": "kids",
|
||||||
"in": "query",
|
"in": "query",
|
||||||
@ -9092,4 +9110,4 @@
|
|||||||
"description": "About",
|
"description": "About",
|
||||||
"url": "https://jikan.moe"
|
"url": "https://jikan.moe"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,6 +15,14 @@ class SeasonControllerTest extends TestCase
|
|||||||
use SyntheticMongoDbTransaction;
|
use SyntheticMongoDbTransaction;
|
||||||
use ScoutFlush;
|
use ScoutFlush;
|
||||||
|
|
||||||
|
private function continuingUrlProvider(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
"?continuing=true" => ["/v4/seasons/2024/winter?continuing=true"],
|
||||||
|
"?continuing" => ["/v4/seasons/2024/winter?continuing"],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function testShouldFilterOutAnimeWithGarbledAiredString()
|
public function testShouldFilterOutAnimeWithGarbledAiredString()
|
||||||
{
|
{
|
||||||
Carbon::setTestNow(Carbon::parse("2024-01-11"));
|
Carbon::setTestNow(Carbon::parse("2024-01-11"));
|
||||||
@ -95,7 +103,53 @@ class SeasonControllerTest extends TestCase
|
|||||||
$this->assertCount(2, $content["data"]);
|
$this->assertCount(2, $content["data"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testShouldNotFilterOutContinuingItemsFromPreviousSeasons()
|
/**
|
||||||
|
* @return void
|
||||||
|
* @dataProvider continuingUrlProvider
|
||||||
|
*/
|
||||||
|
public function testShouldNotFilterOutContinuingItemsFromPreviousSeasons($requestUrl)
|
||||||
|
{
|
||||||
|
Carbon::setTestNow(Carbon::parse("2024-01-11"));
|
||||||
|
// an item in the future airing
|
||||||
|
$f = Anime::factory(1);
|
||||||
|
$startDate = "2024-02-24";
|
||||||
|
$carbonStartDate = Carbon::parse($startDate);
|
||||||
|
$state = $f->serializeStateDefinition([
|
||||||
|
"aired" => new CarbonDateRange($carbonStartDate, null)
|
||||||
|
]);
|
||||||
|
$state["aired"]["string"] = "Feb 24, 2024 to ?";
|
||||||
|
$state["premiered"] = null;
|
||||||
|
$state["status"] = "Not yet aired";
|
||||||
|
$state["airing"] = false;
|
||||||
|
$f->create($state);
|
||||||
|
|
||||||
|
// the absolutely correct item
|
||||||
|
$f = Anime::factory(1);
|
||||||
|
$state = $f->serializeStateDefinition([
|
||||||
|
"aired" => new CarbonDateRange(Carbon::parse("2024-01-10"), Carbon::parse("2024-02-15"))
|
||||||
|
]);
|
||||||
|
$state["premiered"] = "Winter 2024";
|
||||||
|
$state["status"] = "Currently Airing";
|
||||||
|
$state["airing"] = true;
|
||||||
|
$f->create($state);
|
||||||
|
|
||||||
|
// the continuing item
|
||||||
|
$f = Anime::factory(1);
|
||||||
|
$state = $f->serializeStateDefinition([
|
||||||
|
"aired" => new CarbonDateRange(Carbon::parse("2023-10-10"), null)
|
||||||
|
]);
|
||||||
|
$state["premiered"] = "Fall 2023";
|
||||||
|
$state["status"] = "Currently Airing";
|
||||||
|
$state["airing"] = true;
|
||||||
|
$f->create($state);
|
||||||
|
|
||||||
|
$content = $this->getJsonResponse([], $requestUrl);
|
||||||
|
$this->seeStatusCode(200);
|
||||||
|
$this->assertIsArray($content["data"]);
|
||||||
|
$this->assertCount(3, $content["data"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldNotIncludeContinuingItemsByDefault()
|
||||||
{
|
{
|
||||||
Carbon::setTestNow(Carbon::parse("2024-01-11"));
|
Carbon::setTestNow(Carbon::parse("2024-01-11"));
|
||||||
// an item in the future airing
|
// an item in the future airing
|
||||||
@ -134,6 +188,6 @@ class SeasonControllerTest extends TestCase
|
|||||||
$content = $this->getJsonResponse([], "/v4/seasons/2024/winter");
|
$content = $this->getJsonResponse([], "/v4/seasons/2024/winter");
|
||||||
$this->seeStatusCode(200);
|
$this->seeStatusCode(200);
|
||||||
$this->assertIsArray($content["data"]);
|
$this->assertIsArray($content["data"]);
|
||||||
$this->assertCount(3, $content["data"]);
|
$this->assertCount(2, $content["data"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user