feat: filters for /api/users/private/list
This commit is contained in:
parent
27e21f0ad0
commit
ca1f629f05
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Facade\Filters;
|
||||||
|
|
||||||
|
class Filter
|
||||||
|
{
|
||||||
|
public FilterTypeEnum $type;
|
||||||
|
public string $column;
|
||||||
|
public string $filter;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Facade\Filters;
|
||||||
|
|
||||||
|
enum FilterTypeEnum: string
|
||||||
|
{
|
||||||
|
case Is = 'is';
|
||||||
|
case Like = 'like';
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Facade\Filters;
|
||||||
|
use App\Facade\Filters\Pagination;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use JsonMapper;
|
||||||
|
|
||||||
|
class Filters
|
||||||
|
{
|
||||||
|
|
||||||
|
public const FILTERS_VALIDATION = [];
|
||||||
|
// 'filters.*.column' => [ 'required', 'string' ],
|
||||||
|
// 'filters.*.type' => [ 'required', Rule::enum(FilterTypeEnum::class) ],
|
||||||
|
// 'filters.*.filter' => [ 'required', 'string' ],
|
||||||
|
|
||||||
|
// 'orders.*.by' => [ 'required', 'string' ],
|
||||||
|
// 'orders.*.sort' => [ 'required', Rule::enum(OrderTypeEnum::class) ],
|
||||||
|
|
||||||
|
// 'pagination.size' => 'number',
|
||||||
|
// 'pagination.page' => 'number',
|
||||||
|
// ];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Filter[]
|
||||||
|
*/
|
||||||
|
public array $filters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Order[]
|
||||||
|
*/
|
||||||
|
public array $orders;
|
||||||
|
|
||||||
|
public ?Pagination $pagination;
|
||||||
|
|
||||||
|
public static function fromArrayOrObject(array | object $data): Filters
|
||||||
|
{
|
||||||
|
$mapper = new JsonMapper();
|
||||||
|
if (is_array($data)) {
|
||||||
|
$data = json_decode(json_encode($data), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data->filters ??= [];
|
||||||
|
$data->orders ??= [];
|
||||||
|
$data->pagination ??= null;
|
||||||
|
|
||||||
|
return $mapper->map($data, \App\Facade\Filters\Filters::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function apply(Builder $builder)
|
||||||
|
{
|
||||||
|
foreach ($this->filters as $filter) {
|
||||||
|
switch ($filter->type) {
|
||||||
|
case FilterTypeEnum::Is:
|
||||||
|
$builder->where($filter->column, $filter->filter);
|
||||||
|
break;
|
||||||
|
case FilterTypeEnum::Like:
|
||||||
|
$builder->whereLike($filter->column, $filter->filter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->orders as $order) {
|
||||||
|
$builder->orderBy($order->by, $order->sort->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_null($this->pagination)) {
|
||||||
|
$builder->paginate($this->pagination->size , ['*'], 'page', $this->pagination->page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Facade\Filters;
|
||||||
|
|
||||||
|
class Order
|
||||||
|
{
|
||||||
|
public string $by;
|
||||||
|
public OrderTypeEnum $sort;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Facade\Filters;
|
||||||
|
|
||||||
|
enum OrderTypeEnum: string
|
||||||
|
{
|
||||||
|
case Asc = 'asc';
|
||||||
|
case Desc = 'desc';
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Facade\Filters;
|
||||||
|
|
||||||
|
class Pagination
|
||||||
|
{
|
||||||
|
public int $size;
|
||||||
|
public int $page;
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Facade\Filters\Filters;
|
||||||
use App\Http\Requests\AuthorizedRequest;
|
use App\Http\Requests\AuthorizedRequest;
|
||||||
use App\Http\Requests\UserEditRequest;
|
use App\Http\Requests\UserEditRequest;
|
||||||
use App\Services\UserService;
|
use App\Services\UserService;
|
||||||
|
@ -17,6 +18,12 @@ class PrivateUserController extends Controller
|
||||||
return $this->userService->listAll();
|
return $this->userService->listAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function listFilters(AuthorizedRequest $request)
|
||||||
|
{
|
||||||
|
$filters = Filters::fromArrayOrObject($request->all());
|
||||||
|
return $this->userService->listAll($filters);
|
||||||
|
}
|
||||||
|
|
||||||
public function get(AuthorizedRequest $request, string $id)
|
public function get(AuthorizedRequest $request, string $id)
|
||||||
{
|
{
|
||||||
return $this->userService->getOneById($id);
|
return $this->userService->getOneById($id);
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
use App\Facade\Filters\Filters;
|
||||||
|
|
||||||
|
class AuthorizedFilterListRequest extends AuthorizedRequest
|
||||||
|
{
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return Filters::FILTERS_VALIDATION;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
namespace App\Http\Requests;
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
|
|
||||||
class AuthorizedRequest extends RestRequest
|
class AuthorizedRequest extends RestRequest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Facade\Filters\Filters;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
@ -54,10 +55,15 @@ class UserService
|
||||||
$user->save();
|
$user->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function listAll(): array
|
public function listAll(?Filters $filters = null): array
|
||||||
{
|
{
|
||||||
|
if (is_null($filters)) {
|
||||||
return User::all()->toArray();
|
return User::all()->toArray();
|
||||||
}
|
}
|
||||||
|
$builder = User::query();
|
||||||
|
$filters->apply($builder);
|
||||||
|
return $builder->get()->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
public function getOneById(string $id): User | null
|
public function getOneById(string $id): User | null
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
"bjeavons/zxcvbn-php": "^1.3",
|
"bjeavons/zxcvbn-php": "^1.3",
|
||||||
"egulias/email-validator": "^4.0",
|
"egulias/email-validator": "^4.0",
|
||||||
"laravel/framework": "^11.9",
|
"laravel/framework": "^11.9",
|
||||||
"laravel/tinker": "^2.9"
|
"laravel/tinker": "^2.9",
|
||||||
|
"netresearch/jsonmapper": "^4.4"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.23",
|
"fakerphp/faker": "^1.23",
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "847793c6725e2d2fecbf33402e6d4c4d",
|
"content-hash": "029c945e578ceadcd46c7f20984f1cd4",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "bjeavons/zxcvbn-php",
|
"name": "bjeavons/zxcvbn-php",
|
||||||
|
@ -2079,6 +2079,57 @@
|
||||||
],
|
],
|
||||||
"time": "2024-08-19T06:22:39+00:00"
|
"time": "2024-08-19T06:22:39+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "netresearch/jsonmapper",
|
||||||
|
"version": "v4.4.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/cweiske/jsonmapper.git",
|
||||||
|
"reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/132c75c7dd83e45353ebb9c6c9f591952995bbf0",
|
||||||
|
"reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-pcre": "*",
|
||||||
|
"ext-reflection": "*",
|
||||||
|
"ext-spl": "*",
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0",
|
||||||
|
"squizlabs/php_codesniffer": "~3.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"JsonMapper": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"OSL-3.0"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Christian Weiske",
|
||||||
|
"email": "cweiske@cweiske.de",
|
||||||
|
"homepage": "http://github.com/cweiske/jsonmapper/",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Map nested JSON structures onto PHP classes",
|
||||||
|
"support": {
|
||||||
|
"email": "cweiske@cweiske.de",
|
||||||
|
"issues": "https://github.com/cweiske/jsonmapper/issues",
|
||||||
|
"source": "https://github.com/cweiske/jsonmapper/tree/v4.4.1"
|
||||||
|
},
|
||||||
|
"time": "2024-01-31T06:18:54+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "nette/schema",
|
"name": "nette/schema",
|
||||||
"version": "v1.3.0",
|
"version": "v1.3.0",
|
||||||
|
|
|
@ -148,6 +148,30 @@ paths:
|
||||||
description: Auth failed
|
description: Auth failed
|
||||||
403:
|
403:
|
||||||
description: Auth failed
|
description: Auth failed
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Private routes
|
||||||
|
security:
|
||||||
|
- session: []
|
||||||
|
summary: List all users with filters
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Filters'
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
401:
|
||||||
|
description: Auth failed
|
||||||
|
403:
|
||||||
|
description: Auth failed
|
||||||
/api/users/private/get/{id}:
|
/api/users/private/get/{id}:
|
||||||
get:
|
get:
|
||||||
parameters:
|
parameters:
|
||||||
|
@ -424,6 +448,69 @@ components:
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
example: 'This field is invalid!'
|
example: 'This field is invalid!'
|
||||||
|
Filters:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
filters:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Filter'
|
||||||
|
example: [
|
||||||
|
{
|
||||||
|
"column": "name",
|
||||||
|
"type": "like",
|
||||||
|
"filter": "%ad%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"column": "name",
|
||||||
|
"type": "is",
|
||||||
|
"filter": "jade"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
orders:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Order'
|
||||||
|
example: [
|
||||||
|
{
|
||||||
|
"by": "id",
|
||||||
|
"type": "asc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"by": "id",
|
||||||
|
"type": "desc"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
pagination:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
size:
|
||||||
|
type: number
|
||||||
|
example: 100
|
||||||
|
page:
|
||||||
|
type: number
|
||||||
|
example: 1
|
||||||
|
Filter:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
column:
|
||||||
|
type: string
|
||||||
|
example: column_name
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
example: 'is'
|
||||||
|
filter:
|
||||||
|
type: string
|
||||||
|
example: '123'
|
||||||
|
Order:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
by:
|
||||||
|
type: string
|
||||||
|
example: column_name
|
||||||
|
sort:
|
||||||
|
type: string
|
||||||
|
example: 'asc|desc'
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
session:
|
session:
|
||||||
type: http
|
type: http
|
||||||
|
|
|
@ -17,6 +17,7 @@ Route::prefix('/api')->group(function() {
|
||||||
});
|
});
|
||||||
Route::controller(PrivateUserController::class)->prefix('/users/private')->group(function () {
|
Route::controller(PrivateUserController::class)->prefix('/users/private')->group(function () {
|
||||||
Route::get('/list', 'list');
|
Route::get('/list', 'list');
|
||||||
|
Route::post('/list', 'listFilters');
|
||||||
Route::get('/get/{id}', 'get')->whereUuid('id');
|
Route::get('/get/{id}', 'get')->whereUuid('id');
|
||||||
Route::put('/edit/{id}', 'edit')->whereUuid('id');
|
Route::put('/edit/{id}', 'edit')->whereUuid('id');
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue