Skip to content

Commit 4d3a06e

Browse files
committed
feat: add in support for nested api controllers
1 parent fbc71e0 commit 4d3a06e

File tree

4 files changed

+385
-311
lines changed

4 files changed

+385
-311
lines changed

Diff for: src/Concerns/IsApiController.php

+311
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
<?php
2+
3+
namespace Javaabu\QueryBuilder\Concerns;
4+
5+
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
6+
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Database\Eloquent\ModelNotFoundException;
8+
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
9+
use Illuminate\Foundation\Bus\DispatchesJobs;
10+
use Illuminate\Foundation\Validation\ValidatesRequests;
11+
use Illuminate\Http\Request;
12+
use Illuminate\Support\Arr;
13+
use Illuminate\Support\Collection;
14+
use Illuminate\Validation\ValidationException;
15+
use Javaabu\QueryBuilder\QueryBuilder;
16+
use Spatie\QueryBuilder\QueryBuilderRequest;
17+
18+
trait IsApiController
19+
{
20+
use AuthorizesRequests;
21+
use ValidatesRequests;
22+
use DispatchesJobs;
23+
24+
/**
25+
* Query builder request
26+
*
27+
* @var QueryBuilderRequest
28+
*/
29+
protected $query_request;
30+
31+
protected array $additional_params = [];
32+
33+
/**
34+
* Unlimited per page
35+
*
36+
* @return bool
37+
*/
38+
protected function allowUnlimitedResultsPerPage(): bool
39+
{
40+
return property_exists($this, 'allow_unlimited_results') ? $this->allow_unlimited_results : false;
41+
}
42+
43+
/**
44+
* Check if the request wants all the results
45+
*
46+
* @param Request $request
47+
* @return bool
48+
*/
49+
protected function wantsAllResults(Request $request): bool
50+
{
51+
return $request->input('per_page') == -1;
52+
}
53+
54+
/**
55+
* Get per page
56+
*
57+
* @param Request $request
58+
* @param int $default
59+
* @return int
60+
*/
61+
protected function getPerPage(Request $request, int $default = 0)
62+
{
63+
return abs($request->input('per_page', $default));
64+
}
65+
66+
/**
67+
* Display a listing of the resource.
68+
*
69+
* @param Request $request
70+
* @return QueryBuilder[]|LengthAwarePaginator|\Illuminate\Database\Eloquent\Collection|\Spatie\QueryBuilder\QueryBuilder[]
71+
* @throws ValidationException
72+
*/
73+
protected function indexEndpoint(Request $request)
74+
{
75+
76+
$this->validate($request, $this->getIndexValidation());
77+
78+
$query = QueryBuilder::for($this->getBaseQuery());
79+
80+
if ($default_sort = $this->getDefaultSort()) {
81+
$query->defaultSort($default_sort);
82+
}
83+
84+
$query->allowedSorts($this->getAllowedSorts())
85+
->allowedFilters($this->getAllowedFilters())
86+
->allowedAppends($this->getAllowedAppends())
87+
->fieldsToAlwaysInclude($this->getFieldsToAlwaysInclude())
88+
->allowedFields($this->getAllowedFields())
89+
->allowedIncludes($this->getAllowedIncludes());
90+
91+
$query = $this->modifyQuery($query);
92+
93+
if ($this->allowUnlimitedResultsPerPage() && $this->wantsAllResults($request)) {
94+
return $query->get();
95+
}
96+
97+
return $query->paginate($this->getPerPage($request, 10))
98+
->appends($request->except(['page']));
99+
}
100+
101+
/**
102+
* Display a single resource.
103+
*
104+
* @param $model_id
105+
* @param Request $request
106+
* @return \Illuminate\Database\Eloquent\Collection|Model|QueryBuilder|QueryBuilder[]|null
107+
* @throws ValidationException
108+
*/
109+
protected function showEndpoint($model_id, Request $request)
110+
{
111+
$this->validate($request, $this->getShowValidation());
112+
113+
try {
114+
$model = QueryBuilder::for($this->getBaseQuery())
115+
->allowedAppends($this->getAllShowAllowedAppends())
116+
->fieldsToAlwaysInclude($this->getFieldsToAlwaysInclude())
117+
->allowedFields($this->getAllowedFields())
118+
->allowedIncludes($this->getAllowedIncludes());
119+
120+
$model = $this->modifyQuery($model)->findOrFail($model_id);
121+
122+
$this->authorizeView($model);
123+
124+
return $this->modifyModel($model);
125+
} catch (ModelNotFoundException $e) {
126+
abort(404, 'Not Found');
127+
}
128+
}
129+
130+
public function setAdditionalParams(mixed $params): self
131+
{
132+
$this->additional_params = is_array($params) ? $params : func_get_args();
133+
134+
return $this;
135+
}
136+
137+
public function getAdditionalParams(string $key = null): mixed
138+
{
139+
return $key ? $this->additional_params[$key] ?? null : $this->additional_params;
140+
}
141+
142+
/**
143+
* Modify the model
144+
*/
145+
public function modifyModel(Model $model): Model
146+
{
147+
return $model;
148+
}
149+
150+
/**
151+
* Check if allowed to view
152+
*
153+
* @param Model $model
154+
*/
155+
protected function authorizeView(Model $model): void
156+
{
157+
return;
158+
}
159+
160+
/**
161+
* Get the index validation
162+
*/
163+
protected function getIndexValidation(): array
164+
{
165+
return [
166+
'per_page' => "integer|" . ($this->allowUnlimitedResultsPerPage() ? 'min:-1' : 'between:1,50'),
167+
'page' => 'integer|min:1',
168+
];
169+
}
170+
171+
/**
172+
* Get the fields to always include
173+
*/
174+
protected function getFieldsToAlwaysInclude(): array
175+
{
176+
return [
177+
'id'
178+
];
179+
}
180+
181+
/**
182+
* Get the index allowed fields
183+
*/
184+
protected function getIndexAllowedFields(): array
185+
{
186+
return $this->getAllowedFields();
187+
}
188+
189+
/**
190+
* Get the show validation
191+
*/
192+
protected function getShowValidation(): array
193+
{
194+
return [];
195+
}
196+
197+
/**
198+
* Get the query request
199+
*
200+
* @return QueryBuilderRequest
201+
*/
202+
protected function getQueryRequest(): QueryBuilderRequest
203+
{
204+
return $this->query_request;
205+
}
206+
207+
/**
208+
* Get the query fields
209+
*
210+
* @return Collection
211+
*/
212+
protected function fields(): Collection
213+
{
214+
return $this->getQueryRequest()->fields();
215+
}
216+
217+
/**
218+
* Get the query appends
219+
*
220+
* @return Collection
221+
*/
222+
protected function appends(): Collection
223+
{
224+
return $this->getQueryRequest()->appends();
225+
}
226+
227+
/**
228+
* Get the query includes
229+
*
230+
* @return Collection
231+
*/
232+
protected function includes(): Collection
233+
{
234+
return $this->getQueryRequest()->includes();
235+
}
236+
237+
/**
238+
* Get the query sorts
239+
*
240+
* @return Collection
241+
*/
242+
protected function sorts(): Collection
243+
{
244+
return $this->getQueryRequest()->sorts();
245+
}
246+
247+
/**
248+
* Get the query filters
249+
*
250+
* @return Collection
251+
*/
252+
protected function filters(): Collection
253+
{
254+
return $this->getQueryRequest()->filters();
255+
}
256+
257+
/**
258+
* Modify the query after adding query builder params
259+
*
260+
* @param \Spatie\QueryBuilder\QueryBuilder $query
261+
* @return QueryBuilder
262+
*/
263+
protected function modifyQuery(\Spatie\QueryBuilder\QueryBuilder $query): \Spatie\QueryBuilder\QueryBuilder
264+
{
265+
return $query;
266+
}
267+
268+
/**
269+
* Get the allowed append attributes
270+
*
271+
* @return array
272+
*/
273+
protected function getAllowedAppendAttributes(): array
274+
{
275+
return Arr::rootKeys($this->getAllowedAppends());
276+
}
277+
278+
/**
279+
* Get the allowed append attributes
280+
*
281+
* @return array
282+
*/
283+
protected function getShowAllowedAppendAttributes(): array
284+
{
285+
return Arr::rootKeys($this->getAllShowAllowedAppends());
286+
}
287+
288+
/**
289+
* Get the show allowed appends
290+
*/
291+
protected function getAllShowAllowedAppends(): array
292+
{
293+
if (! $this->getShowAllowedAppends()) {
294+
return $this->getAllowedAppends();
295+
}
296+
297+
return array_merge(
298+
$this->getAllowedAppends(),
299+
$this->getShowAllowedAppends()
300+
);
301+
}
302+
303+
304+
/**
305+
* Get the allowed appends for only show endpoint
306+
*/
307+
protected function getShowAllowedAppends(): array
308+
{
309+
return [];
310+
}
311+
}

Diff for: src/Http/Controllers/ApiBaseController.php

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace Javaabu\QueryBuilder\Http\Controllers;
4+
5+
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
6+
use Illuminate\Database\Eloquent\Builder;
7+
use Illuminate\Database\Eloquent\Model;
8+
use Illuminate\Http\Request;
9+
use Illuminate\Routing\Controller as BaseController;
10+
use Illuminate\Validation\ValidationException;
11+
use Javaabu\QueryBuilder\Concerns\IsApiController;
12+
use Javaabu\QueryBuilder\QueryBuilder;
13+
use Spatie\QueryBuilder\QueryBuilderRequest;
14+
15+
abstract class ApiBaseController extends BaseController
16+
{
17+
use IsApiController;
18+
19+
/**
20+
* Constructor
21+
*
22+
* @param QueryBuilderRequest $request
23+
*/
24+
public function __construct(QueryBuilderRequest $request)
25+
{
26+
$this->query_request = $request;
27+
}
28+
29+
/**
30+
* Get the base query
31+
*/
32+
protected abstract function getBaseQuery(): Builder;
33+
34+
/**
35+
* Get the fields
36+
*/
37+
protected abstract function getAllowedFields(): array;
38+
39+
/**
40+
* Get the includes
41+
*/
42+
protected abstract function getAllowedIncludes(): array;
43+
44+
/**
45+
* Get the allowed appends
46+
*/
47+
protected abstract function getAllowedAppends(): array;
48+
49+
/**
50+
* Get the allowed sorts
51+
*/
52+
protected abstract function getAllowedSorts(): array;
53+
54+
/**
55+
* Get the default sort
56+
*/
57+
protected abstract function getDefaultSort(): string;
58+
59+
/**
60+
* Get the allowed filters
61+
*/
62+
protected abstract function getAllowedFilters(): array;
63+
}

0 commit comments

Comments
 (0)