fixed filtering by producer/magazine on anime/manga search endpoints

- additionally improved model factories for tests
This commit is contained in:
pushrbx 2024-04-10 18:59:30 +01:00
parent 2a7fcff329
commit 9de8ffc9db
7 changed files with 141 additions and 25 deletions

View File

@ -181,14 +181,11 @@ class Anime extends JikanApiSearchableModel
} }
$producer = (int)$value; $producer = (int)$value;
/** @noinspection PhpParamsInspection */ return $query->where(function (\Jenssegers\Mongodb\Eloquent\Builder $query) use ($producer) {
return $query->whereRaw([ return $query->where('producers.mal_id', $producer)
'$or' => [ ->orWhere('licensors.mal_id', $producer)
['producers.mal_id' => $producer], ->orWhere('studios.mal_id', $producer);
['licensors.mal_id' => $producer], });
['studios.mal_id' => $producer]
]
]);
} }
/** @noinspection PhpUnused */ /** @noinspection PhpUnused */
@ -198,16 +195,24 @@ class Anime extends JikanApiSearchableModel
return $query; return $query;
} }
$producers = collect(explode(',', $value))->filter()->toArray(); /* @var \Illuminate\Support\Collection $producers */
$orFilters = []; $producers = collect(explode(',', $value))->filter();
foreach ($producers as $producer) {
$producer = (int)$producer; return $query->where(function (\Jenssegers\Mongodb\Eloquent\Builder $query) use ($producers) {
$orFilters[] = ['producers.mal_id' => $producer]; $firstProducer = (int)$producers->first();
$orFilters[] = ['licensors.mal_id' => $producer]; $query = $query->where('producers.mal_id', $firstProducer)
$orFilters[] = ['studios.mal_id' => $producer]; ->orWhere('licensors.mal_id', $firstProducer)
} ->orWhere('studios.mal_id', $firstProducer);
/** @noinspection PhpParamsInspection */
return $query->whereRaw(['$or' => $orFilters]); foreach ($producers->skip(1) as $producer) {
$producer = (int)$producer;
$query = $query->orWhere('producers.mal_id', $producer)
->orWhere('licensors.mal_id', $producer)
->orWhere('studios.mal_id', $producer);
}
return $query;
});
} }
/** @noinspection PhpUnused */ /** @noinspection PhpUnused */

View File

@ -111,14 +111,10 @@ class Manga extends JikanApiSearchableModel
return $query; return $query;
} }
/** @var \Illuminate\Support\Collection $magazines */
$magazines = collect(explode(',', $value))->filter()->map(fn($x) => (int)$x)->toArray(); $magazines = collect(explode(',', $value))->filter()->map(fn($x) => (int)$x)->toArray();
/** @noinspection PhpParamsInspection */ return $query->whereIn("serializations.mal_id", $magazines);
return $query->whereRaw([
"serializations.mal_id" => [
'$in' => $magazines
]
]);
} }
/** @noinspection PhpUnused */ /** @noinspection PhpUnused */

View File

@ -4,6 +4,7 @@ namespace Database\Factories;
use App\CarbonDateRange; use App\CarbonDateRange;
use App\Anime; use App\Anime;
use App\Testing\JikanDataGenerator; use App\Testing\JikanDataGenerator;
use Illuminate\Support\Collection;
use MongoDB\BSON\UTCDateTime; use MongoDB\BSON\UTCDateTime;
@ -139,4 +140,47 @@ class AnimeFactory extends JikanMediaModelFactory
"request_hash" => sprintf("request:%s:%s", "v4", $this->getItemTestUrl("anime", $mal_id)) "request_hash" => sprintf("request:%s:%s", "v4", $this->getItemTestUrl("anime", $mal_id))
]; ];
} }
protected function getOverridesFromQueryStringParameters(Collection $additionalParams): array
{
$overrides = parent::getOverridesFromQueryStringParameters($additionalParams);
if ($additionalParams->has("producers")) {
$overrides["producers"] = [];
$producerIds = explode(",", $additionalParams["producers"]);
foreach ($producerIds as $producerId) {
$overrides["producers"][] = [
"mal_id" => (int)$producerId,
"type" => "anime",
"name" => "Producer ${producerId}",
"url" => "https://myanimelist.net/anime/producer/${producerId}/x"
];
}
}
return $overrides;
}
protected function getOppositeOverridesFromQueryStringParameters(Collection $additionalParams): array
{
$overrides = parent::getOppositeOverridesFromQueryStringParameters($additionalParams);
if ($additionalParams->has("producers")) {
$overrides["producers"] = [];
$producerIds = explode(",", $additionalParams["producers"]);
do {
$randomEls = $this->faker->randomElements([11, 60, 89, 54, 32, 22, 108, 65], $this->faker->numberBetween(1, 3));
} while (count(array_intersect($randomEls, $producerIds)) > 0);
foreach ($randomEls as $producerId) {
$overrides["produces"][] = [
"mal_id" => (int)$producerId,
"type" => "anime",
"name" => "Producer ${producerId}",
"url" => "https://myanimelist.net/anime/producer/${producerId}/x"
];
}
}
return $overrides;
}
} }

View File

@ -7,6 +7,7 @@ use App\Enums\AnimeRatingEnum;
use App\Enums\AnimeTypeEnum; use App\Enums\AnimeTypeEnum;
use App\Enums\MangaTypeEnum; use App\Enums\MangaTypeEnum;
use App\Testing\JikanDataGenerator; use App\Testing\JikanDataGenerator;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -56,6 +57,16 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
* @return self * @return self
*/ */
public function overrideFromQueryStringParameters(array $additionalParams, bool $doOpposite = false): self public function overrideFromQueryStringParameters(array $additionalParams, bool $doOpposite = false): self
{
if ($this->count === 1) {
return $this->state($this->serializeStateDefinition($this->getStateOverrides($additionalParams, $doOpposite)));
}
/** @noinspection PhpParamsInspection */
return $this->state(new Sequence(fn(Sequence $_) => $this->serializeStateDefinition($this->getStateOverrides($additionalParams, $doOpposite))));
}
private function getStateOverrides(array $additionalParams, bool $doOpposite = false): array
{ {
$additionalParams = collect($additionalParams); $additionalParams = collect($additionalParams);
@ -66,7 +77,7 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
$overrides = $this->getOverridesFromQueryStringParameters($additionalParams); $overrides = $this->getOverridesFromQueryStringParameters($additionalParams);
} }
return $this->state($this->serializeStateDefinition($overrides)); return $overrides;
} }
/** /**
@ -158,6 +169,10 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
$overrides = [...$overrides, ...$a]; $overrides = [...$overrides, ...$a];
} }
if ($additionalParams->has("score")) {
$overrides["score"] = floatval($additionalParams["score"]);
}
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)) {
@ -283,6 +298,15 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
$overrides = [...$overrides, ...$a]; $overrides = [...$overrides, ...$a];
} }
if ($additionalParams->has("score")) {
$specifiedScore = floatval($additionalParams["score"]);
do {
$randomScore = $this->faker->randomFloat(2, 1.00, 9.99);
} while ($randomScore === $specifiedScore);
$overrides["score"] = $randomScore;
}
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)) {

View File

@ -4,6 +4,7 @@ namespace Database\Factories;
use App\CarbonDateRange; use App\CarbonDateRange;
use App\Testing\JikanDataGenerator; use App\Testing\JikanDataGenerator;
use App\Manga; use App\Manga;
use Illuminate\Support\Collection;
use MongoDB\BSON\UTCDateTime; use MongoDB\BSON\UTCDateTime;
class MangaFactory extends JikanMediaModelFactory class MangaFactory extends JikanMediaModelFactory
@ -98,4 +99,48 @@ class MangaFactory extends JikanMediaModelFactory
"request_hash" => sprintf("request:%s:%s", "v4", $this->getItemTestUrl("manga", $mal_id)) "request_hash" => sprintf("request:%s:%s", "v4", $this->getItemTestUrl("manga", $mal_id))
]; ];
} }
protected function getOverridesFromQueryStringParameters(Collection $additionalParams): array
{
$overrides = parent::getOverridesFromQueryStringParameters($additionalParams);
if ($additionalParams->has("magazines")) {
$overrides["serializations"] = [];
$magazineIds = explode(",", $additionalParams["magazines"]);
foreach ($magazineIds as $magazineId) {
$overrides["serializations"][] = [
"mal_id" => (int)$magazineId,
"type" => "manga",
"name" => "Magazine {$magazineId}",
"url" => "https://myanimelist.net/manga/magazine/{$magazineId}/x"
];
}
}
return $overrides;
}
protected function getOppositeOverridesFromQueryStringParameters(Collection $additionalParams): array
{
$overrides = parent::getOppositeOverridesFromQueryStringParameters($additionalParams);
if ($additionalParams->has("magazines")) {
$overrides["serializations"] = [];
$magazineIds = explode(",", $additionalParams["magazines"]);
do {
$randomEls = $this->faker->randomElements([11, 60, 89, 54, 32, 22, 108, 65], $this->faker->numberBetween(1, 3));
} while (count(array_intersect($randomEls, $magazineIds)) > 0);
foreach ($randomEls as $magazineId) {
$overrides["serializations"][] = [
"mal_id" => (int)$magazineId,
"type" => "manga",
"name" => "Magazine {$magazineId}",
"url" => "https://myanimelist.net/manga/magazine/{$magazineId}/x"
];
}
}
return $overrides;
}
} }

View File

@ -138,6 +138,7 @@ class AnimeSearchEndpointTest extends TestCase
"type = movie" => [["type" => "movie"]], "type = movie" => [["type" => "movie"]],
"type = ova" => [["type" => "ova"]], "type = ova" => [["type" => "ova"]],
"type = special" => [["type" => "special"]], "type = special" => [["type" => "special"]],
"score = 8 and producers = 11" => [["score" => "8", "producers" => "11"]],
]; ];
} }

View File

@ -128,6 +128,7 @@ class MangaSearchEndpointTest extends TestCase
[["type" => "novel"]], [["type" => "novel"]],
[["type" => "lightnovel"]], [["type" => "lightnovel"]],
[["type" => "oneshot"]], [["type" => "oneshot"]],
[["score" => "8", "magazines" => "83"]]
]; ];
} }