Skip to content

Commit efbfc1b

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents 13001fe + f835a48 commit efbfc1b

File tree

9 files changed

+64
-12
lines changed

9 files changed

+64
-12
lines changed

src/Contracts/Paginator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
interface Paginator
88
{
9-
public function __construct(int $defaultLimit);
9+
public function __construct(int $defaultLimit, int $maxLimit);
1010

1111
public function resolvePaginationLimit(Request $request): int;
1212
}

src/Drivers/Standard/Paginator.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Orion\Drivers\Standard;
44

5+
use Orion\Exceptions\MaxPaginationLimitExceededException;
56
use Orion\Http\Requests\Request;
67

78
class Paginator implements \Orion\Contracts\Paginator
@@ -11,14 +12,20 @@ class Paginator implements \Orion\Contracts\Paginator
1112
*/
1213
protected $defaultLimit;
1314

15+
/**
16+
* @var int $maxLimit
17+
*/
18+
protected $maxLimit;
19+
1420
/**
1521
* Paginator constructor.
1622
*
1723
* @param int $defaultLimit
1824
*/
19-
public function __construct(int $defaultLimit)
25+
public function __construct(int $defaultLimit, int $maxLimit)
2026
{
2127
$this->defaultLimit = $defaultLimit;
28+
$this->maxLimit = $maxLimit;
2229
}
2330

2431
/**
@@ -29,7 +36,11 @@ public function __construct(int $defaultLimit)
2936
*/
3037
public function resolvePaginationLimit(Request $request): int
3138
{
32-
$limit = (int)$request->get('limit', $this->defaultLimit);
33-
return $limit > 0 ? $limit : $this->defaultLimit;
39+
$limit = (int)$request->get('limit');
40+
return tap($limit > 0 ? $limit : $this->defaultLimit, function ($limit) {
41+
if ($limit > $this->maxLimit) {
42+
throw new MaxPaginationLimitExceededException(422, __("Pagination limit of :max is exceeded. Current: :limit", ['max' => $this->maxLimit, 'limit' => $limit]));
43+
}
44+
});
3445
}
3546
}

src/Drivers/Standard/ParamsValidator.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,9 @@ public function validateAggregators(Request $request): void
119119
'regex:/^[\w.\_\-\>]+$/',
120120
],
121121
'aggregates.*.field' => [
122-
(float) app()->version() >= 8.32 ? 'prohibited_if:aggregate.*.type,count' : '',
123-
(float) app()->version() >= 8.32 ? 'prohibited_if:aggregate.*.type,exists' : '',
124-
'required_if:aggregate.*.type,avg,sum,min,max',
122+
(float) app()->version() >= 8.32 ? 'prohibited_if:aggregates.*.type,count' : '',
123+
(float) app()->version() >= 8.32 ? 'prohibited_if:aggregates.*.type,exists' : '',
124+
'required_if:aggregates.*.type,avg,sum,min,max',
125125
],
126126
'aggregates.*.type' => [
127127
'required',
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Orion\Exceptions;
4+
5+
use Symfony\Component\HttpKernel\Exception\HttpException;
6+
7+
class MaxPaginationLimitExceededException extends HttpException
8+
{
9+
10+
}

src/Http/Controllers/BaseController.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ public function __construct()
127127
Paginator::class,
128128
[
129129
'defaultLimit' => $this->limit(),
130+
'maxLimit' => $this->maxLimit()
130131
]
131132
);
132133
$this->searchBuilder = App::makeWith(
@@ -245,6 +246,16 @@ public function limit(): int
245246
return 15;
246247
}
247248

249+
/**
250+
* Max pagination limit.
251+
*
252+
* @return int
253+
*/
254+
public function maxLimit(): int
255+
{
256+
return 500;
257+
}
258+
248259
/**
249260
* The attributes that are used for searching.
250261
*

tests/Feature/StandardIndexOperationsTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Support\Facades\Gate;
66
use Mockery;
77
use Orion\Contracts\ComponentsResolver;
8+
use Orion\Exceptions\MaxPaginationLimitExceededException;
89
use Orion\Tests\Fixtures\App\Http\Resources\SampleCollectionResource;
910
use Orion\Tests\Fixtures\App\Http\Resources\SampleResource;
1011
use Orion\Tests\Fixtures\App\Models\Post;

tests/Unit/Drivers/Standard/PaginatorTest.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,29 @@
22

33
namespace Orion\Tests\Unit\Drivers\Standard;
44

5+
use Illuminate\Support\Facades\Gate;
56
use Orion\Drivers\Standard\Paginator;
7+
use Orion\Exceptions\MaxPaginationLimitExceededException;
68
use Orion\Http\Requests\Request;
9+
use Orion\Tests\Fixtures\App\Models\Post;
10+
use Orion\Tests\Fixtures\App\Models\User;
11+
use Orion\Tests\Fixtures\App\Policies\GreenPolicy;
712
use Orion\Tests\Unit\TestCase;
813

914
class PaginatorTest extends TestCase
1015
{
1116
/** @test */
1217
public function resolving_default_pagination_limit()
1318
{
14-
$paginator = new Paginator(15);
19+
$paginator = new Paginator(15, 500);
1520

1621
$this->assertSame(15, $paginator->resolvePaginationLimit(Request::create('/api/posts')));
1722
}
1823

1924
/** @test */
2025
public function resolving_pagination_limit_from_request()
2126
{
22-
$paginator = new Paginator(15);
27+
$paginator = new Paginator(15, 500);
2328
$request = Request::create('/api/posts');
2429
$request->query->set('limit', 30);
2530

@@ -29,10 +34,22 @@ public function resolving_pagination_limit_from_request()
2934
/** @test */
3035
public function falling_back_to_default_pagination_limit()
3136
{
32-
$paginator = new Paginator(15);
37+
$paginator = new Paginator(15, 500);
3338
$request = Request::create('/api/posts');
3439
$request->query->set('limit', 0);
3540

3641
$this->assertSame(15, $paginator->resolvePaginationLimit($request));
3742
}
43+
44+
/** @test */
45+
public function getting_a_list_of_resources_with_exceeded_pagination_limit(): void
46+
{
47+
$paginator = new Paginator(15, 500);
48+
$request = Request::create('/api/posts');
49+
$request->query->set('limit', 501);
50+
51+
$this->expectException(MaxPaginationLimitExceededException::class);
52+
53+
$paginator->resolvePaginationLimit($request);
54+
}
3855
}

tests/Unit/Http/Controllers/BaseControllerTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function dependencies_are_resolved_correctly()
4141
$fakeComponentsResolver = new ComponentsResolver(Post::class);
4242
$fakeParamsValidator = new ParamsValidator();
4343
$fakeRelationsResolver = new RelationsResolver([], []);
44-
$fakePaginator = new Paginator(15);
44+
$fakePaginator = new Paginator(15, 500);
4545
$fakeSearchBuilder = new SearchBuilder([]);
4646
$fakeQueryBuilder = new QueryBuilder(Post::class, $fakeParamsValidator, $fakeRelationsResolver, $fakeSearchBuilder);
4747

@@ -75,6 +75,7 @@ public function dependencies_are_resolved_correctly()
7575
\Orion\Contracts\Paginator::class,
7676
[
7777
'defaultLimit' => 15,
78+
'maxLimit' => 500,
7879
]
7980
)->once()->andReturn($fakePaginator);
8081

tests/Unit/Http/Controllers/RelationControllerTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function dependencies_are_resolved_correctly()
3434
$fakeComponentsResolver = new ComponentsResolver(Post::class);
3535
$fakeParamsValidator = new ParamsValidator();
3636
$fakeRelationsResolver = new RelationsResolver([], []);
37-
$fakePaginator = new Paginator(15);
37+
$fakePaginator = new Paginator(15, 500);
3838
$fakeSearchBuilder = new SearchBuilder([]);
3939
$fakeQueryBuilder = new QueryBuilder(Post::class, $fakeParamsValidator, $fakeRelationsResolver, $fakeSearchBuilder);
4040
$fakeRelationQueryBuilder = new QueryBuilder(User::class, $fakeParamsValidator, $fakeRelationsResolver, $fakeSearchBuilder);
@@ -69,6 +69,7 @@ public function dependencies_are_resolved_correctly()
6969
\Orion\Contracts\Paginator::class,
7070
[
7171
'defaultLimit' => 15,
72+
'maxLimit' => 500,
7273
]
7374
)->once()->andReturn($fakePaginator);
7475

0 commit comments

Comments
 (0)