Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨Feature: Allows random endpoints to return multiple items #559

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
2 changes: 0 additions & 2 deletions app/Contracts/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,4 @@ public function tableName(): string;
public function scrape(int|string $id): array;

public function insert(array $attributes): bool;

public function random(int $numberOfRandomItems = 1): Collection;
}
2 changes: 2 additions & 0 deletions app/Dto/Concerns/HasLimitParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* @OA\Parameter(
* name="limit",
* in="query",
* required=false,
* description="Maximum limit (and the default number of entries returned) is 25 for all endpoints except for Random endpoints where the maximum limit is 5 and the default number of entries returned is 1.",
* @OA\Schema(type="integer")
* ),
*/
Expand Down
17 changes: 17 additions & 0 deletions app/Dto/Concerns/HasLimitParameterWithSmallerMax.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace App\Dto\Concerns;

use App\Rules\Attributes\MaxLimitWithFallback;
use OpenApi\Annotations as OA;
use Spatie\LaravelData\Attributes\Validation\IntegerType;
use Spatie\LaravelData\Attributes\Validation\Min;
use Spatie\LaravelData\Optional;

trait HasLimitParameterWithSmallerMax
{
use PreparesData;

#[IntegerType, Min(1), MaxLimitWithFallback(5)]
public int|Optional $limit;
}
11 changes: 7 additions & 4 deletions app/Dto/Concerns/PreparesData.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ trait PreparesData
public static function prepareForPipeline(Collection $properties): Collection
{
// let's always set the limit parameter to the globally configured default value
if (property_exists(static::class, "limit") && !$properties->has("limit")) {
$properties->put("limit", max_results_per_page(
property_exists(static::class, "defaultLimit") ? static::$defaultLimit : null));
}
// // BUG: this causes override and always sets the default limit to config value
// even if the property `limit` does not exist
// max_results_per_page never accepts $defaultLimit and will always return config value
// if (property_exists(static::class, "limit") && !$properties->has("limit")) {
// $properties->put("limit", max_results_per_page(
// property_exists(static::class, "defaultLimit") ? static::$defaultLimit : null));
// }

// we want to cast "true" and "false" string values to boolean before validation, so let's take all properties
// of the class which are bool or bool|Optional type, and using their name read the values from the incoming
Expand Down
3 changes: 2 additions & 1 deletion app/Dto/QueryRandomAnimeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
*/
final class QueryRandomAnimeCommand extends Data implements DataRequest
{
use HasSfwParameter, HasUnapprovedParameter;
use HasSfwParameter,
HasUnapprovedParameter;
}
20 changes: 20 additions & 0 deletions app/Dto/QueryRandomAnimeListCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Dto;

use App\Contracts\DataRequest;
use App\Dto\Concerns\HasLimitParameterWithSmallerMax;
use App\Dto\Concerns\HasSfwParameter;
use App\Dto\Concerns\HasUnapprovedParameter;
use App\Http\Resources\V4\AnimeCollection;
use Spatie\LaravelData\Data;

/**
* @implements DataRequest<AnimeCollection>
*/
final class QueryRandomAnimeListCommand extends Data implements DataRequest
{
use HasSfwParameter,
HasUnapprovedParameter,
HasLimitParameterWithSmallerMax;
}
1 change: 1 addition & 0 deletions app/Dto/QueryRandomCharacterCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Dto;

use App\Contracts\DataRequest;
use App\Dto\Concerns\HasLimitParameterWithSmallerMax;
use App\Http\Resources\V4\CharacterResource;
use Spatie\LaravelData\Data;

Expand Down
16 changes: 16 additions & 0 deletions app/Dto/QueryRandomCharacterListCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace App\Dto;

use App\Contracts\DataRequest;
use App\Dto\Concerns\HasLimitParameterWithSmallerMax;
use App\Http\Resources\V4\CharacterCollection;
use Spatie\LaravelData\Data;

/**
* @implements DataRequest<CharacterCollection>
*/
final class QueryRandomCharacterListCommand extends Data implements DataRequest
{
use HasLimitParameterWithSmallerMax;
}
3 changes: 2 additions & 1 deletion app/Dto/QueryRandomMangaCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
*/
final class QueryRandomMangaCommand extends Data implements DataRequest
{
use HasSfwParameter, HasUnapprovedParameter;
use HasSfwParameter,
HasUnapprovedParameter;
}
20 changes: 20 additions & 0 deletions app/Dto/QueryRandomMangaListCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Dto;

use App\Contracts\DataRequest;
use App\Dto\Concerns\HasLimitParameterWithSmallerMax;
use App\Dto\Concerns\HasSfwParameter;
use App\Dto\Concerns\HasUnapprovedParameter;
use App\Http\Resources\V4\MangaCollection;
use Spatie\LaravelData\Data;

/**
* @implements DataRequest<MangaCollection>
*/
final class QueryRandomMangaListCommand extends Data implements DataRequest
{
use HasSfwParameter,
HasUnapprovedParameter,
HasLimitParameterWithSmallerMax;
}
16 changes: 16 additions & 0 deletions app/Dto/QueryRandomPersonListCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace App\Dto;

use App\Contracts\DataRequest;
use App\Dto\Concerns\HasLimitParameterWithSmallerMax;
use App\Http\Resources\V4\PersonCollection;
use Spatie\LaravelData\Data;

/**
* @implements DataRequest<PersonCollection>
*/
final class QueryRandomPersonListCommand extends Data implements DataRequest
{
use HasLimitParameterWithSmallerMax;
}
1 change: 1 addition & 0 deletions app/Dto/QueryRandomUserCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Dto;

use App\Contracts\DataRequest;
use App\Dto\Concerns\HasLimitParameterWithSmallerMax;
use App\Http\Resources\V4\ProfileResource;
use Spatie\LaravelData\Data;

Expand Down
16 changes: 16 additions & 0 deletions app/Dto/QueryRandomUserListCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace App\Dto;

use App\Contracts\DataRequest;
use App\Dto\Concerns\HasLimitParameterWithSmallerMax;
use App\Http\Resources\V4\UserCollection;
use Spatie\LaravelData\Data;

/**
* @implements DataRequest<UserCollection>
*/
final class QueryRandomUserListCommand extends Data implements DataRequest
{
use HasLimitParameterWithSmallerMax;
}
2 changes: 0 additions & 2 deletions app/Dto/QuerySpecificAnimeSeasonCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ final class QuerySpecificAnimeSeasonCommand extends QueryAnimeSeasonCommand
#[WithCast(EnumCast::class, AnimeSeasonEnum::class), EnumValidation(AnimeSeasonEnum::class)]
public AnimeSeasonEnum $season;

protected static int $defaultLimit = 30;

public static function messages(...$args): array
{
return [
Expand Down
3 changes: 2 additions & 1 deletion app/Features/QueryAnimeSchedulesHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Http\Resources\V4\AnimeCollection;
use App\Support\CachedData;
use Illuminate\Support\Env;
use Spatie\LaravelData\Optional;

/**
* @implements RequestHandler<QueryAnimeSchedulesCommand, AnimeCollection>
Expand All @@ -24,7 +25,7 @@ public function __construct(private readonly AnimeRepository $repository)
public function handle($request)
{
$requestParams = collect($request->all());
$limit = $requestParams->get("limit");
$limit = $request->limit instanceof Optional ? max_results_per_page() : $request->limit;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is repeating code, shouldn't we either change the PreparesData to replace Optional with this?

$results = $this->repository->getCurrentlyAiring($request->filter);
// apply sfw, kids and unapproved filters
/** @noinspection PhpUndefinedMethodInspection */
Expand Down
4 changes: 3 additions & 1 deletion app/Features/QueryAnimeSeasonHandlerBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Illuminate\Contracts\Database\Query\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Carbon;
use Spatie\LaravelData\Optional;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;

/**
Expand All @@ -32,11 +33,12 @@ public function handle($request): JsonResponse
{
$requestParams = collect($request->all());
$type = $requestParams->has("filter") ? $request->filter : null;
$limit = $request->limit instanceof Optional ? max_results_per_page() : $request->limit;
$results = $this->getSeasonItems($request, $type);
// apply sfw, kids and unapproved filters
/** @noinspection PhpUndefinedMethodInspection */
$results = $results->filter($requestParams);
$results = $results->paginate($request->limit, ["*"], null, $request->page);
$results = $results->paginate($limit, ["*"], null, $request->page);

$animeCollection = new AnimeCollection($results);
$response = $animeCollection->response();
Expand Down
11 changes: 5 additions & 6 deletions app/Features/QueryRandomAnimeHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,12 @@
{
$queryable = Anime::query();

$o = Optional::create();
$sfwParam = $request->sfw === $o ? false : $request->sfw;
$unapprovedParam = $request->unapproved === $o ? false : $request->unapproved;
$sfwParam = $request->sfw instanceof Optional ? false : $request->sfw;
$unapprovedParam = $request->unapproved instanceof Optional ? false : $request->unapproved;

Check warning on line 24 in app/Features/QueryRandomAnimeHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomAnimeHandler.php#L23-L24

Added lines #L23 - L24 were not covered by tests

return new AnimeResource(
$queryable->random(1, $sfwParam, $unapprovedParam)->first()
);
$results = $queryable->random(1, $sfwParam, $unapprovedParam);

Check warning on line 26 in app/Features/QueryRandomAnimeHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomAnimeHandler.php#L26

Added line #L26 was not covered by tests

return new AnimeResource($results->first());

Check warning on line 28 in app/Features/QueryRandomAnimeHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomAnimeHandler.php#L28

Added line #L28 was not covered by tests
}

/**
Expand Down
40 changes: 40 additions & 0 deletions app/Features/QueryRandomAnimeListHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace App\Features;

use App\Anime;
use App\Contracts\RequestHandler;
use App\Dto\QueryRandomAnimeCommand;
use App\Dto\QueryRandomAnimeListCommand;
use App\Http\Resources\V4\AnimeCollection;
use Spatie\LaravelData\Optional;

/**
* @implements RequestHandler<QueryRandomAnimeCommand, AnimeCollection>
*/
final class QueryRandomAnimeListHandler implements RequestHandler
{
/**
* @inheritDoc
*/
public function handle($request): AnimeCollection

Check warning on line 20 in app/Features/QueryRandomAnimeListHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomAnimeListHandler.php#L20

Added line #L20 was not covered by tests
{
$queryable = Anime::query();

Check warning on line 22 in app/Features/QueryRandomAnimeListHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomAnimeListHandler.php#L22

Added line #L22 was not covered by tests

$sfwParam = $request->sfw instanceof Optional ? false : $request->sfw;
$unapprovedParam = $request->unapproved instanceof Optional ? false : $request->unapproved;
$limit = $request->limit instanceof Optional ? 1 : $request->limit;

Check warning on line 26 in app/Features/QueryRandomAnimeListHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomAnimeListHandler.php#L24-L26

Added lines #L24 - L26 were not covered by tests

$results = $queryable->random($limit, $sfwParam, $unapprovedParam);

Check warning on line 28 in app/Features/QueryRandomAnimeListHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomAnimeListHandler.php#L28

Added line #L28 was not covered by tests

return new AnimeCollection($results, false);

Check warning on line 30 in app/Features/QueryRandomAnimeListHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomAnimeListHandler.php#L30

Added line #L30 was not covered by tests
}

/**
* @inheritDoc
*/
public function requestClass(): string
{
return QueryRandomAnimeListCommand::class;
}
}
26 changes: 14 additions & 12 deletions app/Features/QueryRandomCharacterHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,27 @@

namespace App\Features;

use App\Contracts\CharacterRepository;
use App\Character;
use App\Contracts\RequestHandler;
use App\Dto\QueryRandomCharacterCommand;
use App\Http\Resources\V4\CharacterResource;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;

/**
* @extends QueryRandomItemHandler<QueryRandomCharacterCommand, CharacterResource>
* @extends QueryRandomCharacterHandler<QueryRandomCharacterCommand, CharacterResource>
*/
final class QueryRandomCharacterHandler extends QueryRandomItemHandler
final class QueryRandomCharacterHandler implements RequestHandler
{
public function __construct(CharacterRepository $repository)

/**
* @inheritDoc
*/
public function handle($request): CharacterResource

Check warning on line 19 in app/Features/QueryRandomCharacterHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomCharacterHandler.php#L19

Added line #L19 was not covered by tests
{
parent::__construct($repository);
return new CharacterResource(
Character::query()
->random(1)
->first()
);

Check warning on line 25 in app/Features/QueryRandomCharacterHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomCharacterHandler.php#L21-L25

Added lines #L21 - L25 were not covered by tests
}

/**
Expand All @@ -25,9 +32,4 @@
{
return QueryRandomCharacterCommand::class;
}

protected function resource(Collection $results): JsonResource
{
return new CharacterResource($results->first());
}
}
35 changes: 35 additions & 0 deletions app/Features/QueryRandomCharacterListHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace App\Features;

use App\Character;
use App\Contracts\RequestHandler;
use App\Dto\QueryRandomCharacterListCommand;
use App\Http\Resources\V4\CharacterCollection;
use Spatie\LaravelData\Optional;

/**
* @implements RequestHandler<QueryRandomCharacterListCommand, CharacterCollection>
*/
final class QueryRandomCharacterListHandler implements RequestHandler
{
/**
* @inheritDoc
*/
public function handle($request): CharacterCollection

Check warning on line 19 in app/Features/QueryRandomCharacterListHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomCharacterListHandler.php#L19

Added line #L19 was not covered by tests
{
$queryable = Character::query();
$limit = $request->limit instanceof Optional ? 1 : $request->limit;
$results = $queryable->random($limit);

Check warning on line 23 in app/Features/QueryRandomCharacterListHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomCharacterListHandler.php#L21-L23

Added lines #L21 - L23 were not covered by tests

return new CharacterCollection($results, false);

Check warning on line 25 in app/Features/QueryRandomCharacterListHandler.php

View check run for this annotation

Codecov / codecov/patch

app/Features/QueryRandomCharacterListHandler.php#L25

Added line #L25 was not covered by tests
}

/**
* @inheritDoc
*/
public function requestClass(): string
{
return QueryRandomCharacterListCommand::class;
}
}
Loading