feat(RequestHelper): add pagination and URI conversion methods
Implement pagination logic and methods to convert request URLs to League URI instances.
This commit is contained in:
parent
8855f74bf0
commit
05ececd879
3 changed files with 175 additions and 76 deletions
47
src/Infra/Http/Helpers/RequestHelper.php
Normal file
47
src/Infra/Http/Helpers/RequestHelper.php
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Infra\Http\Helpers;
|
||||
|
||||
use Illuminate\Http\Request as HttpRequest;
|
||||
use League\Uri\Http;
|
||||
use Shared\Pagination;
|
||||
|
||||
final class RequestHelper
|
||||
{
|
||||
private function __construct()
|
||||
{
|
||||
// Static class
|
||||
}
|
||||
|
||||
public static function pagination(HttpRequest $request, int $defaultPageSize = 25): Pagination
|
||||
{
|
||||
if ($request->has('offset') || $request->has('limit')) {
|
||||
return Pagination::ofOffsetAndLimit(
|
||||
$request->integer('offset', 0),
|
||||
$request->integer('limit', $defaultPageSize)
|
||||
);
|
||||
}
|
||||
|
||||
$pageSize = $request->integer(
|
||||
'pageSize',
|
||||
$request->integer('per_page', $request->integer('pagination', $defaultPageSize))
|
||||
);
|
||||
|
||||
return Pagination::ofPage(
|
||||
$request->integer('page', 1),
|
||||
$pageSize
|
||||
);
|
||||
}
|
||||
|
||||
public static function toLeagueUri(HttpRequest $request): Http
|
||||
{
|
||||
return Http::new($request->url());
|
||||
}
|
||||
|
||||
public static function toLeagueFullUri(HttpRequest $request): Http
|
||||
{
|
||||
return Http::new($request->fullUrl());
|
||||
}
|
||||
}
|
||||
|
|
@ -4,10 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Infra\Providers;
|
||||
|
||||
use Carbon\CarbonInterface;
|
||||
use Illuminate\Cache\RateLimiting\Limit;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request as HttpRequest;
|
||||
use Illuminate\Http\Request as IlluminateRequest;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
|
|
@ -15,6 +13,7 @@ use Illuminate\Support\Facades\RateLimiter;
|
|||
use Illuminate\Support\Facades\Request;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Infra\Http\Helpers\RequestHelper;
|
||||
use League\Uri\Http;
|
||||
use Shared\Pagination;
|
||||
|
||||
|
|
@ -56,93 +55,30 @@ class AppServiceProvider extends ServiceProvider
|
|||
Date::setLocale(Config::string('app.locale'));
|
||||
Date::setFallbackLocale(Config::string('app.fallback_locale'));
|
||||
|
||||
$provider = $this;
|
||||
|
||||
Date::macro('toLocalInput', function (CarbonInterface | \DateTimeInterface | int | float | string | null $date) use ($provider): ?string {
|
||||
return $provider->toLocalInput($date);
|
||||
Request::macro('pagination', function (int $defaultPageSize = 25): Pagination {
|
||||
/** @var \Illuminate\Http\Request $this */
|
||||
return RequestHelper::pagination($this, $defaultPageSize);
|
||||
});
|
||||
|
||||
Date::macro('forHumans', function (CarbonInterface | \DateTimeInterface | int | float | string | null $date) use ($provider): ?string {
|
||||
return $provider->forHumans($date);
|
||||
Request::macro('toLeagueUri', function (): Http {
|
||||
/** @var \Illuminate\Http\Request $this */
|
||||
return RequestHelper::toLeagueUri($this);
|
||||
});
|
||||
|
||||
Request::macro('pagination', function (int $defaultPageSize = 25) use ($provider): Pagination {
|
||||
return $provider->pagination(request(), $defaultPageSize);
|
||||
});
|
||||
|
||||
Request::macro('toLeagueUri', function () use ($provider): Http {
|
||||
return $provider->toLeagueUri(request());
|
||||
});
|
||||
|
||||
Request::macro('toLeagueFullUri', function () use ($provider): Http {
|
||||
return $provider->toLeagueFullUri(request());
|
||||
Request::macro('toLeagueFullUri', function (): Http {
|
||||
/** @var \Illuminate\Http\Request $this */
|
||||
return RequestHelper::toLeagueFullUri($this);
|
||||
});
|
||||
}
|
||||
|
||||
protected function configureRateLimiting(): void
|
||||
{
|
||||
RateLimiter::for('web', function (IlluminateRequest $request) {
|
||||
RateLimiter::for('web', function (IlluminateRequest $_) {
|
||||
return Limit::perMinute(Config::integer('throttles.web'))->by(resolve('clientIp'));
|
||||
});
|
||||
|
||||
RateLimiter::for('api.v1', function (IlluminateRequest $request) {
|
||||
RateLimiter::for('api.v1', function (IlluminateRequest $_) {
|
||||
return Limit::perMinute(Config::integer('throttles.api.v1'))->by(resolve('clientIp'));
|
||||
});
|
||||
}
|
||||
|
||||
public function toLocalInput(CarbonInterface | \DateTimeInterface | int | float | string | null $date): ?string
|
||||
{
|
||||
if ($date === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$timezone = request()->string('client_timezone', 'Europe/Paris')->value();
|
||||
|
||||
return Date::parse($date)
|
||||
->setTimezone($timezone)
|
||||
->format('Y-m-d\TH:i');
|
||||
}
|
||||
|
||||
public function forHumans(CarbonInterface | \DateTimeInterface | int | float | string | null $date): ?string
|
||||
{
|
||||
if ($date === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$timezone = request()->string('client_timezone', 'Europe/Paris')->value();
|
||||
|
||||
return Date::parse($date)
|
||||
->setTimezone($timezone)
|
||||
->isoFormat('ddd DD/MM/Y \à HH:mm');
|
||||
}
|
||||
|
||||
public function pagination(HttpRequest $request, int $defaultPageSize): Pagination
|
||||
{
|
||||
if ($request->has('offset') || $request->has('limit')) {
|
||||
return Pagination::ofOffsetAndLimit(
|
||||
$request->integer('offset', 0),
|
||||
$request->integer('limit', $defaultPageSize)
|
||||
);
|
||||
}
|
||||
|
||||
$pageSize = $request->integer(
|
||||
'pageSize',
|
||||
$request->integer('per_page', $request->integer('pagination', $defaultPageSize))
|
||||
);
|
||||
|
||||
return Pagination::ofPage(
|
||||
$request->integer('page', 1),
|
||||
$pageSize
|
||||
);
|
||||
}
|
||||
|
||||
public function toLeagueUri(HttpRequest $request): Http
|
||||
{
|
||||
return Http::new($request->url());
|
||||
}
|
||||
|
||||
public function toLeagueFullUri(HttpRequest $request): Http
|
||||
{
|
||||
return Http::new($request->fullUrl());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
116
tests/Unit/Infra/Http/Helpers/RequestHelperTest.php
Normal file
116
tests/Unit/Infra/Http/Helpers/RequestHelperTest.php
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Infra\Http\Helpers;
|
||||
|
||||
use Illuminate\Http\Request as HttpRequest;
|
||||
use Infra\Http\Helpers\RequestHelper;
|
||||
use League\Uri\Http;
|
||||
use Shared\Pagination;
|
||||
|
||||
covers(RequestHelper::class);
|
||||
|
||||
describe('RequestHelper Unit Tests', function (): void {
|
||||
it('prevents direct instantiation but covers constructor', function (): void {
|
||||
// GIVEN
|
||||
$reflection = new \ReflectionClass(RequestHelper::class);
|
||||
|
||||
// WHEN
|
||||
$constructor = $reflection->getConstructor();
|
||||
$constructor?->invoke($reflection->newInstanceWithoutConstructor());
|
||||
|
||||
// THEN
|
||||
expect(fn () => $reflection->newInstance())
|
||||
->toThrow(\ReflectionException::class);
|
||||
});
|
||||
|
||||
it('creates offset and limit pagination when offset or limit query param is present', function (): void {
|
||||
// GIVEN
|
||||
$request = HttpRequest::create('/api/v1/employees?offset=10&limit=50', 'GET');
|
||||
|
||||
// WHEN
|
||||
$pagination = RequestHelper::pagination($request, 25);
|
||||
|
||||
// THEN
|
||||
expect($pagination)->toBeInstanceOf(Pagination::class)
|
||||
->and($pagination->from())->toBe(10)
|
||||
->and($pagination->to())->toBe(59);
|
||||
});
|
||||
|
||||
it('creates page and page size pagination using pageSize query param', function (): void {
|
||||
// GIVEN
|
||||
$request = HttpRequest::create('/api/v1/employees?page=2&pageSize=15', 'GET');
|
||||
|
||||
// WHEN
|
||||
$pagination = RequestHelper::pagination($request, 25);
|
||||
|
||||
// THEN
|
||||
expect($pagination)->toBeInstanceOf(Pagination::class)
|
||||
->and($pagination->from())->toBe(15)
|
||||
->and($pagination->to())->toBe(29);
|
||||
});
|
||||
|
||||
it('creates page and page size pagination using per_page query param fallback', function (): void {
|
||||
// GIVEN
|
||||
$request = HttpRequest::create('/api/v1/employees?page=3&per_page=20', 'GET');
|
||||
|
||||
// WHEN
|
||||
$pagination = RequestHelper::pagination($request, 25);
|
||||
|
||||
// THEN
|
||||
expect($pagination)->toBeInstanceOf(Pagination::class)
|
||||
->and($pagination->from())->toBe(40)
|
||||
->and($pagination->to())->toBe(59);
|
||||
});
|
||||
|
||||
it('creates page and page size pagination using pagination query param fallback', function (): void {
|
||||
// GIVEN
|
||||
$request = HttpRequest::create('/api/v1/employees?page=1&pagination=30', 'GET');
|
||||
|
||||
// WHEN
|
||||
$pagination = RequestHelper::pagination($request, 25);
|
||||
|
||||
// THEN
|
||||
expect($pagination)->toBeInstanceOf(Pagination::class)
|
||||
->and($pagination->from())->toBe(0)
|
||||
->and($pagination->to())->toBe(29);
|
||||
});
|
||||
|
||||
it('uses default page size when no pagination parameters are supplied', function (): void {
|
||||
// GIVEN
|
||||
$request = HttpRequest::create('/api/v1/employees', 'GET');
|
||||
|
||||
// WHEN
|
||||
$pagination = RequestHelper::pagination($request, 25);
|
||||
|
||||
// THEN
|
||||
expect($pagination)->toBeInstanceOf(Pagination::class)
|
||||
->and($pagination->from())->toBe(0)
|
||||
->and($pagination->to())->toBe(24);
|
||||
});
|
||||
|
||||
it('converts request URL to League Uri instance', function (): void {
|
||||
// GIVEN
|
||||
$request = HttpRequest::create('http://localhost/api/v1/employees?foo=bar', 'GET');
|
||||
|
||||
// WHEN
|
||||
$uri = RequestHelper::toLeagueUri($request);
|
||||
|
||||
// THEN
|
||||
expect($uri)->toBeInstanceOf(Http::class)
|
||||
->and((string) $uri)->toBe('http://localhost/api/v1/employees');
|
||||
});
|
||||
|
||||
it('converts full request URL with query parameters to League Uri instance', function (): void {
|
||||
// GIVEN
|
||||
$request = HttpRequest::create('http://localhost/api/v1/employees?page=2&pageSize=10', 'GET');
|
||||
|
||||
// WHEN
|
||||
$uri = RequestHelper::toLeagueFullUri($request);
|
||||
|
||||
// THEN
|
||||
expect($uri)->toBeInstanceOf(Http::class)
|
||||
->and((string) $uri)->toBe('http://localhost/api/v1/employees?page=2&pageSize=10');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue