Skip to content

Commit d939faf

Browse files
authored
Feature/policy collections update (#22)
* Develop (#14) * Added Created, Updated and Deleted events, Moved request to each method to allow overloading: * Apply fixes from StyleCI * Scrutinizer updates * Update controller.stub * Feature/requests mapping (#13) * Event accepts request object and any type of request can now be pushed through * Apply fixes from StyleCI (#12) * Request should have a constructor for instances with models * Update BaseRepository.php * Apply fixes from StyleCI (#15) * Fixed namespace type declaration * Fixed namespace type declaration * Fixed namespace type declaration * Develop To Master (#16) * Added Created, Updated and Deleted events, Moved request to each method to allow overloading: * Apply fixes from StyleCI * Scrutinizer updates * Update controller.stub * Feature/requests mapping (#13) * Event accepts request object and any type of request can now be pushed through * Apply fixes from StyleCI (#12) * Request should have a constructor for instances with models * Update BaseRepository.php * Apply fixes from StyleCI (#15) * Fixed namespace type declaration * Fixed namespace type declaration * Fixed namespace type declaration * Added resource collections and policy check. * Updated Readme * Formatting * Apply fixes from StyleCI (#20) * Scrutinizer fixes - deprecation / namesapce * Added middleware and query qualifiers * Policy Update * Post adding new and artisan updated, code cleanup * Apply fixes from StyleCI (#21) * Scrutiniser fixes * Put now handles relations * Fix return types * Minor updates to fix relationships and make command * Sanke case vs camel case * Apply fixes from StyleCI (#23) * Minor bugfix for case sensitifity * Fixed make command * model is static * Apply fixes from StyleCI (#24) * Scrutiniser fixes * Apply fixes from StyleCI (#25)
1 parent e91159e commit d939faf

17 files changed

+970
-412
lines changed

README.md

+7
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ Generate with `php artisan make:policy PostPolicy --model=Post`
5454
* Put Update - calls the `update` policy
5555
* Delete item - calls the `delete` policy
5656

57+
Query/Data modifiers in policies for the api endpoints
58+
59+
* `qualifyCollectionQueryWithUser($user, $repository)` -> return void - add any queries to the repository (ie ->where('x','))
60+
* `qualifyItemQueryWithUser($user, $repository)`-> return void - add any queries to the repository (ie ->where('x','))
61+
* `qualifyStoreDataWithUser($data)` - return the updated data array
62+
* `qualifyUpdateDataWithUser($data)` - return the updated data array
63+
5764
## Resources / Collections (Transforming)
5865
Resources: https://laravel.com/docs/6.x/eloquent-resources
5966

src/Contracts/ModelRepository.php

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
3+
namespace Phpsa\LaravelApiController\Contracts;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Support\Facades\Schema;
7+
use Phpsa\LaravelApiController\Exceptions\ApiException;
8+
use Phpsa\LaravelApiController\Repository\BaseRepository;
9+
10+
trait ModelRepository
11+
{
12+
/**
13+
* Eloquent model instance.
14+
*
15+
* @var mixed|Model instance
16+
*/
17+
protected static $model;
18+
19+
/**
20+
* Repository instance.
21+
*
22+
* @var mixed|BaseRepository
23+
*/
24+
protected $repository;
25+
26+
/**
27+
* Holds the available table columns.
28+
*
29+
* @var array
30+
*/
31+
protected $tableColumns = [];
32+
33+
/**
34+
* @throws ApiException
35+
*/
36+
protected function makeModel(): void
37+
{
38+
$model = resolve($this->model());
39+
40+
if (! $model instanceof Model) {
41+
throw new ApiException("Class {$this->model()} must be an instance of ".Model::class);
42+
}
43+
44+
self::$model = $model;
45+
}
46+
47+
/**
48+
* Creates our repository linkage.
49+
*/
50+
protected function makeRepository()
51+
{
52+
$this->repository = BaseRepository::withModel($this->model());
53+
}
54+
55+
/**
56+
* Set which columns area available in the model.
57+
*
58+
* @param Model $model
59+
*/
60+
protected function setTableColumns(?Model $model = null): void
61+
{
62+
if (is_null($model)) {
63+
$model = self::$model;
64+
}
65+
$table = $model->getTable();
66+
$this->tableColumns[$table] = Schema::getColumnListing($table);
67+
}
68+
69+
/**
70+
* gets avaialble columns for the table.
71+
*
72+
* @param Model $model
73+
*
74+
* @return array
75+
*/
76+
protected function getTableColumns(?Model $model = null): array
77+
{
78+
if (is_null($model)) {
79+
$model = self::$model;
80+
}
81+
82+
$table = $model->getTable();
83+
84+
if (! isset($this->tableColumns[$table])) {
85+
$this->setTableColumns($model);
86+
}
87+
88+
return $this->tableColumns[$table];
89+
}
90+
91+
/**
92+
* Eloquent model.
93+
*
94+
* @return string (model classname)
95+
*/
96+
abstract protected function model();
97+
98+
/**
99+
* Unguard eloquent model if needed.
100+
*/
101+
protected function unguardIfNeeded()
102+
{
103+
if ($this->unguard) {
104+
self::$model->unguard();
105+
}
106+
}
107+
}

src/Traits/Parser.php renamed to src/Contracts/Parser.php

+38-64
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
<?php
22

3-
namespace Phpsa\LaravelApiController\Traits;
3+
namespace Phpsa\LaravelApiController\Contracts;
44

5-
use Illuminate\Database\Eloquent\Model;
6-
use Illuminate\Support\Facades\Schema;
75
use Phpsa\LaravelApiController\Exceptions\UnknownColumnException;
6+
use Phpsa\LaravelApiController\UriParser;
87

98
trait Parser
109
{
@@ -13,55 +12,21 @@ trait Parser
1312
*
1413
* @var \Phpsa\LaravelApiController\UriParser
1514
*/
16-
protected $uriParser;
15+
protected static $uriParser;
1716

18-
/**
19-
* Holds the available table columns.
20-
*
21-
* @var array
22-
*/
23-
protected $tableColumns = [];
24-
25-
/**
26-
* Set which columns area available in the model.
27-
*
28-
* @param Model $model
29-
*/
30-
protected function setTableColumns(Model $model = null) : void
17+
protected function getUriParser($request)
3118
{
32-
if (null === $model) {
33-
$model = $this->model;
19+
if (is_null(self::$uriParser)) {
20+
self::$uriParser = new UriParser($request, config('laravel-api-controller.parameters.filter'));
3421
}
35-
$table = $model->getTable();
36-
$this->tableColumns[$table] = Schema::getColumnListing($table);
37-
}
3822

39-
/**
40-
* gets avaialble columns for the table.
41-
*
42-
* @param Model $model
43-
*
44-
* @return array
45-
*/
46-
protected function getTableColumns(Model $model = null) : array
47-
{
48-
if (null === $model) {
49-
$model = $this->model;
50-
}
51-
52-
$table = $model->getTable();
53-
54-
if (! isset($this->tableColumns[$table])) {
55-
$this->setTableColumns($model);
56-
}
57-
58-
return $this->tableColumns[$table];
23+
return self::$uriParser;
5924
}
6025

6126
/**
6227
* Parses our include joins.
6328
*/
64-
protected function parseIncludeParams() : void
29+
protected function parseIncludeParams(): void
6530
{
6631
$field = config('laravel-api-controller.parameters.include');
6732

@@ -77,8 +42,11 @@ protected function parseIncludeParams() : void
7742

7843
$withs = explode(',', $includes);
7944

45+
/** @scrutinizer ignore-call */
46+
$withs = $this->filterAllowedIncludes($withs);
47+
8048
foreach ($withs as $idx => $with) {
81-
$sub = $this->model->{$with}()->getRelated();
49+
$sub = self::$model->{$with}()->getRelated();
8250
$fields = $this->getIncludesFields($with);
8351

8452
if (! empty($fields)) {
@@ -93,19 +61,21 @@ protected function parseIncludeParams() : void
9361
/**
9462
* Parses our sort parameters.
9563
*/
96-
protected function parseSortParams() : void
64+
protected function parseSortParams(): void
9765
{
9866
$sorts = $this->getSortValue();
9967

10068
foreach ($sorts as $sort) {
10169
$sortP = explode(' ', $sort);
10270
$sortF = $sortP[0];
10371

104-
if (empty($sortF) || ! in_array($sortF, $this->getTableColumns())) {
72+
/** @scrutinizer ignore-call */
73+
$tableColumns = $this->getTableColumns();
74+
if (empty($sortF) || ! in_array($sortF, $tableColumns)) {
10575
continue;
10676
}
10777

108-
$sortD = ! empty($sortP[1]) && strtolower($sortP[1]) == 'desc' ? 'desc' : 'asc';
78+
$sortD = ! empty($sortP[1]) && strtolower($sortP[1]) === 'desc' ? 'desc' : 'asc';
10979
$this->repository->orderBy($sortF, $sortD);
11080
}
11181
}
@@ -115,7 +85,7 @@ protected function parseSortParams() : void
11585
*
11686
* @returns array
11787
*/
118-
protected function getSortValue() : array
88+
protected function getSortValue(): array
11989
{
12090
$field = config('laravel-api-controller.parameters.sort');
12191
$sort = $field && $this->request->has($field) ? $this->request->input($field) : $this->defaultSort;
@@ -130,19 +100,22 @@ protected function getSortValue() : array
130100
/**
131101
* parses our filter parameters.
132102
*/
133-
protected function parseFilterParams() : void
103+
protected function parseFilterParams(): void
134104
{
135-
$where = $this->uriParser->whereParameters();
105+
$where = self::$uriParser->whereParameters();
136106

137107
if (empty($where)) {
138108
return;
139109
}
140110

111+
/** @scrutinizer ignore-call */
112+
$tableColumns = $this->getTableColumns();
113+
141114
foreach ($where as $whr) {
142115
if (strpos($whr['key'], '.') > 0) {
143116
//@TODO: test if exists in the withs, if not continue out to exclude from the qbuild
144117
//continue;
145-
} elseif (! in_array($whr['key'], $this->getTableColumns())) {
118+
} elseif (! in_array($whr['key'], $tableColumns)) {
146119
continue;
147120
}
148121

@@ -155,7 +128,7 @@ protected function parseFilterParams() : void
155128
*
156129
* @param array $where the where clause
157130
*/
158-
protected function setWhereClause($where) : void
131+
protected function setWhereClause($where): void
159132
{
160133
switch ($where['type']) {
161134
case 'In':
@@ -178,40 +151,41 @@ protected function setWhereClause($where) : void
178151
* parses the fields to return.
179152
*
180153
* @throws UnknownColumnException
154+
*
181155
* @return array
182156
*/
183-
protected function parseFieldParams() : array
157+
protected function parseFieldParams(): array
184158
{
185159
$fields = $this->request->has('fields') && ! empty($this->request->input('fields')) ? explode(',', $this->request->input('fields')) : $this->defaultFields;
186-
foreach ($fields as $k => $field) {
187-
if (
188-
$field === '*' ||
189-
in_array($field, $this->getTableColumns())
190-
) {
160+
/** @scrutinizer ignore-call */
161+
$tableColumns = $this->getTableColumns();
162+
foreach ($fields as $key => $field) {
163+
if ($field === '*' || in_array($field, $tableColumns)) {
191164
continue;
192165
}
193-
unset($fields[$k]);
166+
unset($fields[$key]);
194167
}
195168

196169
return $fields;
197170
}
198171

199172
/**
200173
* Parses an includes fields and returns as an array.
174+
*
201175
* @param string $include - the table definer
202176
*
203177
* @return array
204178
*/
205-
protected function getIncludesFields(string $include) : array
179+
protected function getIncludesFields(string $include): array
206180
{
207181
$fields = $this->request->has('fields') && ! empty($this->request->input('fields')) ? explode(',', $this->request->input('fields')) : $this->defaultFields;
208-
foreach ($fields as $k => $field) {
182+
foreach ($fields as $key => $field) {
209183
if (strpos($field, $include.'.') === false) {
210-
unset($fields[$k]);
184+
unset($fields[$key]);
211185

212186
continue;
213187
}
214-
$fields[$k] = str_replace($include.'.', '', $field);
188+
$fields[$key] = str_replace($include.'.', '', $field);
215189
}
216190

217191
return $fields;
@@ -222,7 +196,7 @@ protected function getIncludesFields(string $include) : array
222196
*
223197
* @return int
224198
*/
225-
protected function parseLimitParams() : int
199+
protected function parseLimitParams(): int
226200
{
227201
$limit = $this->request->has('limit') ? intval($this->request->input('limit')) : $this->defaultLimit;
228202

0 commit comments

Comments
 (0)