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;
|
||||
|
||||
use Blax\Workkit\Attributes\VariablePaginatable;
|
||||
use Blax\Workkit\Commands\Database\BackupCommand;
|
||||
use Blax\Workkit\Commands\Database\PruneBackupsCommand;
|
||||
use Blax\Workkit\Commands\Database\RestoreCommand;
|
||||
use Blax\Workkit\Commands\PlugNPrayCommand;
|
||||
use Illuminate\Http\Request;
|
||||
use ReflectionException;
|
||||
use ReflectionMethod;
|
||||
|
||||
class WorkkitServiceProvider extends \Illuminate\Support\ServiceProvider
|
||||
{
|
||||
|
|
@ -26,6 +30,8 @@ class WorkkitServiceProvider extends \Illuminate\Support\ServiceProvider
|
|||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->registerPerPageMacro();
|
||||
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->commands([
|
||||
PlugNPrayCommand::class,
|
||||
|
|
@ -41,4 +47,50 @@ class WorkkitServiceProvider extends \Illuminate\Support\ServiceProvider
|
|||
], '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