diff --git a/config/cp.php b/config/cp.php index 8f9234455a..090e6e8b04 100644 --- a/config/cp.php +++ b/config/cp.php @@ -68,7 +68,7 @@ 'pagination_size' => 50, - 'pagination_size_options' => [10, 25, 50, 100, 500], + 'pagination_size_options' => [10, 25, 50, 100], /* |-------------------------------------------------------------------------- diff --git a/src/Fieldtypes/Entries.php b/src/Fieldtypes/Entries.php index 9fc3881511..81e1971e3e 100644 --- a/src/Fieldtypes/Entries.php +++ b/src/Fieldtypes/Entries.php @@ -27,6 +27,7 @@ use Statamic\Query\StatusQueryBuilder; use Statamic\Search\Index; use Statamic\Search\Result; +use Statamic\Statamic; use Statamic\Support\Arr; use function Statamic\trans as __; @@ -181,7 +182,7 @@ public function getIndexItems($request) $query->orderBy($sort, $this->getSortDirection($request)); } - $results = ($paginate = $request->boolean('paginate', true)) ? $query->paginate($request->integer('perPage', 15)) : $query->get(); + $results = ($paginate = $request->boolean('paginate', true)) ? $query->paginate($request->filled('perPage') ? Statamic::cpPerPage($request->integer('perPage')) : 15) : $query->get(); $items = $results->map(fn ($item) => $item instanceof Result ? $item->getSearchable() : $item); diff --git a/src/Fieldtypes/Terms.php b/src/Fieldtypes/Terms.php index d9ce93ce68..b1b3ee9a49 100644 --- a/src/Fieldtypes/Terms.php +++ b/src/Fieldtypes/Terms.php @@ -25,6 +25,7 @@ use Statamic\Query\OrderedQueryBuilder; use Statamic\Query\Scopes\Filter; use Statamic\Query\Scopes\Filters\Fields\Terms as TermsFilter; +use Statamic\Statamic; use Statamic\Support\Arr; use Statamic\Support\Str; @@ -297,7 +298,7 @@ public function getIndexItems($request) $query->orderBy($sort, $this->getSortDirection($request)); } - return $request->boolean('paginate', true) ? $query->paginate($request->integer('perPage', 15)) : $query->get(); + return $request->boolean('paginate', true) ? $query->paginate($request->filled('perPage') ? Statamic::cpPerPage($request->integer('perPage')) : 15) : $query->get(); } private function authorizeTaxonomyAccess(array $taxonomies): void diff --git a/src/Fieldtypes/Users.php b/src/Fieldtypes/Users.php index 0f154e948c..6a5c63dd8d 100644 --- a/src/Fieldtypes/Users.php +++ b/src/Fieldtypes/Users.php @@ -14,6 +14,7 @@ use Statamic\Query\Scopes\Filter; use Statamic\Query\Scopes\Filters\Fields\User as UserFilter; use Statamic\Search\Result; +use Statamic\Statamic; use Statamic\Support\Arr; use function Statamic\trans as __; @@ -169,7 +170,7 @@ public function getIndexItems($request) }; if ($request->boolean('paginate', true)) { - $users = $query->paginate($request->integer('perPage', 15)); + $users = $query->paginate($request->filled('perPage') ? Statamic::cpPerPage($request->integer('perPage')) : 15); $users->getCollection()->transform($userFields); diff --git a/src/Http/Controllers/CP/Assets/BrowserController.php b/src/Http/Controllers/CP/Assets/BrowserController.php index 905ce98f28..0a48fc9674 100644 --- a/src/Http/Controllers/CP/Assets/BrowserController.php +++ b/src/Http/Controllers/CP/Assets/BrowserController.php @@ -22,6 +22,7 @@ use Statamic\Http\Resources\CP\Concerns\HasRequestedColumns; use Statamic\Query\OrderBy; use Statamic\Query\Scopes\Filters\Concerns\QueriesFilters; +use Statamic\Statamic; use Statamic\Support\Arr; use function Statamic\trans as __; @@ -102,7 +103,7 @@ public function folder(Request $request, $container, $path = '/') $this->authorize('view', $container); $folder = $container->assetFolder($path); - $perPage = $request->perPage ?? config('statamic.cp.pagination_size'); + $perPage = Statamic::cpPerPage($request->perPage) ?? config('statamic.cp.pagination_size'); $page = Paginator::resolveCurrentPage(); $folders = $folder->assetFolders(); @@ -206,7 +207,7 @@ public function search(FilteredRequest $request, $container, $path = null) 'folder' => $path, ]); - $assets = $query->paginate(request('perPage')); + $assets = $query->paginate(Statamic::cpPerPage(request('perPage'))); if ($request->search && $container->hasSearchIndex()) { $assets->setCollection($assets->getCollection()->map->getSearchable()); diff --git a/src/Http/Controllers/CP/Collections/EntriesController.php b/src/Http/Controllers/CP/Collections/EntriesController.php index 4730c635a3..a2392a4d0f 100644 --- a/src/Http/Controllers/CP/Collections/EntriesController.php +++ b/src/Http/Controllers/CP/Collections/EntriesController.php @@ -20,6 +20,7 @@ use Statamic\Http\Resources\CP\Entries\Entry as EntryResource; use Statamic\Query\OrderBy; use Statamic\Query\Scopes\Filters\Concerns\QueriesFilters; +use Statamic\Statamic; use Statamic\Support\Arr; use Statamic\Support\Str; use Statamic\Support\Traits\Hookable; @@ -55,7 +56,7 @@ public function index(FilteredRequest $request, $collection) $query->orderBy($sortField, $sortDirection); } - $entries = (new EntriesIndexQuery($query, $collection))->paginate(request('perPage')); + $entries = (new EntriesIndexQuery($query, $collection))->paginate(Statamic::cpPerPage(request('perPage'))); if (request('search') && $collection->hasSearchIndex()) { $entries->setCollection($entries->getCollection()->map->getSearchable()); diff --git a/src/Http/Controllers/CP/Forms/FormSubmissionsController.php b/src/Http/Controllers/CP/Forms/FormSubmissionsController.php index 1042ffb6b5..d11dc23ca6 100644 --- a/src/Http/Controllers/CP/Forms/FormSubmissionsController.php +++ b/src/Http/Controllers/CP/Forms/FormSubmissionsController.php @@ -9,6 +9,7 @@ use Statamic\Http\Resources\CP\Submissions\Submissions; use Statamic\Query\OrderBy; use Statamic\Query\Scopes\Filters\Concerns\QueriesFilters; +use Statamic\Statamic; class FormSubmissionsController extends CpController { @@ -35,7 +36,7 @@ public function index(FilteredRequest $request, $form) $query->orderBy($sortField, $sortDirection); } - $submissions = $query->paginate(request('perPage')); + $submissions = $query->paginate(Statamic::cpPerPage(request('perPage'))); return (new Submissions($submissions)) ->blueprint($form->blueprint()) diff --git a/src/Http/Controllers/CP/Taxonomies/TermsController.php b/src/Http/Controllers/CP/Taxonomies/TermsController.php index 12439d908f..4479ef43b0 100644 --- a/src/Http/Controllers/CP/Taxonomies/TermsController.php +++ b/src/Http/Controllers/CP/Taxonomies/TermsController.php @@ -17,6 +17,7 @@ use Statamic\Query\Scopes\Filters\Concerns\QueriesFilters; use Statamic\Rules\Slug; use Statamic\Rules\UniqueTermValue; +use Statamic\Statamic; use function Statamic\trans as __; @@ -48,7 +49,7 @@ public function index(FilteredRequest $request, $taxonomy) $query->orderBy($sortField, $sortDirection); } - $paginator = $query->paginate(request('perPage')); + $paginator = $query->paginate(Statamic::cpPerPage(request('perPage'))); $terms = $paginator->getCollection(); diff --git a/src/Http/Controllers/CP/Users/UsersController.php b/src/Http/Controllers/CP/Users/UsersController.php index f10a60ae6f..5cb78449dd 100644 --- a/src/Http/Controllers/CP/Users/UsersController.php +++ b/src/Http/Controllers/CP/Users/UsersController.php @@ -22,6 +22,7 @@ use Statamic\Query\Scopes\Filters\Concerns\QueriesFilters; use Statamic\Rules\UniqueUserValue; use Statamic\Search\Result; +use Statamic\Statamic; use Symfony\Component\Mailer\Exception\TransportException; use function Statamic\trans as __; @@ -95,7 +96,7 @@ protected function json($request) $query->orderBy($sortField, $sortDirection); } - $users = $query->paginate(request('perPage')); + $users = $query->paginate(Statamic::cpPerPage(request('perPage'))); if ($users->getCollection()->first() instanceof Result) { $users->setCollection($users->getCollection()->map->getSearchable()); diff --git a/src/Statamic.php b/src/Statamic.php index 7a7748e6d4..67e9cf59ad 100644 --- a/src/Statamic.php +++ b/src/Statamic.php @@ -477,6 +477,20 @@ public static function cpDirection() return TextDirection::of(static::cpLocale()); } + public static function cpPerPage($perPage) + { + if ($perPage === null || $perPage === '') { + return null; + } + + $perPage = (int) $perPage; + + $options = config('statamic.cp.pagination_size_options') ?: [config('statamic.cp.pagination_size')]; + $ceiling = max($options); + + return max(1, min($perPage, $ceiling)); + } + public static function nonInertiaPageData() { $props = Inertia::getShared(); diff --git a/tests/StatamicTest.php b/tests/StatamicTest.php index bc2614e28f..b6c536861b 100644 --- a/tests/StatamicTest.php +++ b/tests/StatamicTest.php @@ -330,4 +330,39 @@ public function customAssetUrl($app) { $app['config']->set('app.asset_url', 'http://test-asset-url.com'); } + + #[Test] + #[DataProvider('cpPerPageProvider')] + public function it_resolves_cp_per_page($input, $expected) + { + config(['statamic.cp.pagination_size_options' => [10, 25, 50, 100, 500]]); + + $this->assertSame($expected, Statamic::cpPerPage($input)); + } + + public static function cpPerPageProvider() + { + return [ + 'in range' => [10, 10], + 'at ceiling' => [500, 500], + 'above ceiling' => [99999, 500], + 'numeric string above ceiling' => ['99999', 500], + 'null' => [null, null], + 'empty string' => ['', null], + 'zero' => [0, 1], + 'negative' => [-5, 1], + ]; + } + + #[Test] + public function cp_per_page_falls_back_to_pagination_size_when_options_empty() + { + config([ + 'statamic.cp.pagination_size_options' => [], + 'statamic.cp.pagination_size' => 50, + ]); + + $this->assertSame(50, Statamic::cpPerPage(1000)); + $this->assertSame(25, Statamic::cpPerPage(25)); + } }