A variable pagination
This commit is contained in:
parent
8bb3e6499a
commit
c15d1f9475
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Blax\Workkit\Attributes;
|
||||||
|
|
||||||
|
use Attribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares per-method pagination policy for a controller action.
|
||||||
|
*
|
||||||
|
* `Request::perPage()` reads this attribute via reflection on the resolved
|
||||||
|
* route action and produces the page size to hand to `->paginate()`:
|
||||||
|
*
|
||||||
|
* #[VariablePaginatable] → 25, user can override (1..100)
|
||||||
|
* #[VariablePaginatable(50)] → 50, user can override (1..100)
|
||||||
|
* #[VariablePaginatable(10, allowUserOverride: false)] → fixed at 10, no `?per_page=`
|
||||||
|
* #[VariablePaginatable(50, max: 200)] → 50, user can override (1..200)
|
||||||
|
*
|
||||||
|
* Without the attribute, `Request::perPage()` falls back to its $fallback
|
||||||
|
* argument (15 by default — matches Eloquent's model default).
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* #[VariablePaginatable(50)]
|
||||||
|
* public function index(Request $request): array
|
||||||
|
* {
|
||||||
|
* return ResponseService::apiPaginated(
|
||||||
|
* Book::query()->paginate($request->perPage()),
|
||||||
|
* BookResource::class,
|
||||||
|
* );
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
#[Attribute(Attribute::TARGET_METHOD)]
|
||||||
|
final class VariablePaginatable
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public int $default = 25,
|
||||||
|
public bool $allowUserOverride = true,
|
||||||
|
public int $max = 100,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,10 +2,14 @@
|
||||||
|
|
||||||
namespace Blax\Workkit;
|
namespace Blax\Workkit;
|
||||||
|
|
||||||
|
use Blax\Workkit\Attributes\VariablePaginatable;
|
||||||
use Blax\Workkit\Commands\Database\BackupCommand;
|
use Blax\Workkit\Commands\Database\BackupCommand;
|
||||||
use Blax\Workkit\Commands\Database\PruneBackupsCommand;
|
use Blax\Workkit\Commands\Database\PruneBackupsCommand;
|
||||||
use Blax\Workkit\Commands\Database\RestoreCommand;
|
use Blax\Workkit\Commands\Database\RestoreCommand;
|
||||||
use Blax\Workkit\Commands\PlugNPrayCommand;
|
use Blax\Workkit\Commands\PlugNPrayCommand;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use ReflectionException;
|
||||||
|
use ReflectionMethod;
|
||||||
|
|
||||||
class WorkkitServiceProvider extends \Illuminate\Support\ServiceProvider
|
class WorkkitServiceProvider extends \Illuminate\Support\ServiceProvider
|
||||||
{
|
{
|
||||||
|
|
@ -26,6 +30,8 @@ class WorkkitServiceProvider extends \Illuminate\Support\ServiceProvider
|
||||||
*/
|
*/
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
|
$this->registerPerPageMacro();
|
||||||
|
|
||||||
if ($this->app->runningInConsole()) {
|
if ($this->app->runningInConsole()) {
|
||||||
$this->commands([
|
$this->commands([
|
||||||
PlugNPrayCommand::class,
|
PlugNPrayCommand::class,
|
||||||
|
|
@ -41,4 +47,50 @@ class WorkkitServiceProvider extends \Illuminate\Support\ServiceProvider
|
||||||
], 'workkit-config');
|
], 'workkit-config');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the effective page size for the current route via the
|
||||||
|
* {@see VariablePaginatable} attribute on the controller method.
|
||||||
|
*
|
||||||
|
* Order of resolution:
|
||||||
|
* 1. No route / closure action / no attribute → $fallback (default 15)
|
||||||
|
* 2. Attribute present, allowUserOverride=true → clamp `?per_page=N`
|
||||||
|
* into `[1, max]`, defaulting to `default` when the query is missing.
|
||||||
|
* 3. Attribute present, allowUserOverride=false → `default` (ignores query).
|
||||||
|
*/
|
||||||
|
private function registerPerPageMacro(): void
|
||||||
|
{
|
||||||
|
Request::macro('perPage', function (int $fallback = 15): int {
|
||||||
|
/** @var Request $this */
|
||||||
|
$route = $this->route();
|
||||||
|
$controller = is_object($route?->getController()) ? $route->getController()::class : null;
|
||||||
|
$action = is_string($route?->getActionMethod()) ? $route->getActionMethod() : null;
|
||||||
|
|
||||||
|
if (! $controller || ! $action) {
|
||||||
|
return $fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$reflection = new ReflectionMethod($controller, $action);
|
||||||
|
} catch (ReflectionException) {
|
||||||
|
return $fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attributes = $reflection->getAttributes(VariablePaginatable::class);
|
||||||
|
if ($attributes === []) {
|
||||||
|
return $fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var VariablePaginatable $config */
|
||||||
|
$config = $attributes[0]->newInstance();
|
||||||
|
|
||||||
|
if (! $config->allowUserOverride) {
|
||||||
|
return $config->default;
|
||||||
|
}
|
||||||
|
|
||||||
|
$requested = (int) $this->query('per_page', (string) $config->default);
|
||||||
|
|
||||||
|
return min(max($requested, 1), $config->max);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue