Skip to content

Commit 5380d75

Browse files
authored
Develop (#37)
* 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 * Feature/requests mapping (#17) * 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 (#18) * Feature/policy collections update (#19) * 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 * 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) * Apply fixes from StyleCI (#27) * Policiies auth mehtod without users * user not needed * Tidy up uri parser class * Fixes * fix more * Feature/policy collections update (#29) * 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 * policies - for unauthed users * Minor updates * STYLEFIXES * fixed phpcs rule * Apply fixes from StyleCI (#31) * Feature/policy collections update (#32) * 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 * policies - for unauthed users * Minor updates * STYLEFIXES * fixed phpcs rule * Apply fixes from StyleCI (#31) * minor updates * csfixer run on code * Missing file updated * Includes should be returnable * static not defined * Allowed fields updated * minor updates * Logic inversion (#35) * Develop (#33) * 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 * Feature/requests mapping (#17) * 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 (#18) * Feature/policy collections update (#19) * 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 * 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) * Apply fixes from StyleCI (#27) * Policiies auth mehtod without users * user not needed * Tidy up uri parser class * Fixes * fix more * Feature/policy collections update (#29) * 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 * policies - for unauthed users * Minor updates * STYLEFIXES * fixed phpcs rule * Apply fixes from StyleCI (#31) * Feature/policy collections update (#32) * 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 * policies - for unauthed users * Minor updates * STYLEFIXES * fixed phpcs rule * Apply fixes from StyleCI (#31) * minor updates * csfixer run on code * Missing file updated * Includes should be returnable * static not defined * Allowed fields updated * minor updates * Logic inversion + Updated excludeArrayValues to exclude if not in optionals instead of always including. * Added accessor notes about $appends usage * Update controller with query modifier * Add extra query parser method * Include previous exception with ApiException * Api Exception update * Fixed query param optionals * updated unit tests * Updated travis ci config / requirements to laravel / php versions * Put mismatched method back in * Apply fixes from StyleCI (#36)
1 parent 63cc29a commit 5380d75

File tree

9 files changed

+148
-18
lines changed

9 files changed

+148
-18
lines changed

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ notifications:
88
on_failure: always
99

1010
php:
11-
- 7.1
1211
- 7.2
12+
- 7.3
13+
- 7.4
1314

1415
env:
15-
- LARAVEL_VERSION=5.8.*
16+
- LARAVEL_VERSION=6.*
1617

1718
before_install:
1819
- travis_retry composer self-update --stable -n

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ By default all fields are returned, you can limit that to specific fields in the
120120
* Api Controller parameter `$defaultFields` default as `protected $defaultFields = ['*'];` - switch to include an array of fields
121121
* fields param in url querystring: ie `fields=id,name,age` = will only return those, this will also override the above.
122122
* in your response resource you can set the static::allowedFields to lock down which fields are returnable
123-
* addfields and removefields params in url querystring will work with these.
123+
* `addfields` and `removefields` params in url querystring will work with these.
124+
* Use laravel [eloquent model `$appends`](https://laravel.com/docs/6.x/eloquent-serialization#appending-values-to-json) property to automatically include custom attribute accessors.
124125

125126
## Relationships
126127

composer.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
}
1616
],
1717
"require": {
18-
"php": ">=7.1.3",
19-
"illuminate/support": "~5.8.0|^6.0"
18+
"php": ">=7.2",
19+
"illuminate/support": "^6.0"
2020
},
2121
"require-dev": {
22-
"orchestra/testbench": "~3.8.0",
23-
"phpunit/phpunit": "^7.0"
22+
"orchestra/testbench": "^4.0",
23+
"phpunit/phpunit": "^8.0"
2424
},
2525
"autoload": {
2626
"psr-4": {

src/Contracts/Parser.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@ protected function getUriParser($request)
2323
return self::$uriParser;
2424
}
2525

26+
/**
27+
* Method to add extra request parameters to the request instance.
28+
*
29+
* @param mixed $request
30+
* @param array $extraParams
31+
*/
32+
protected function addCustomParams($request, array $extraParams = []): void
33+
{
34+
$all = $request->all();
35+
$new = array_merge_recursive($all, $extraParams);
36+
$request->replace($new);
37+
}
38+
2639
/**
2740
* Parses our include joins.
2841
*/

src/Contracts/Validation.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ protected function rulesForUpdate(/* @scrutinizer ignore-unused */$id): array
5959
*
6060
* @param mixed $role role name or array of role names
6161
*
62+
* @deprecated -- should be rather used in policies / gates
63+
*
6264
* @return bool
6365
*/
6466
protected function hasRole($role): bool
@@ -73,6 +75,8 @@ protected function hasRole($role): bool
7375
*
7476
* @param array $roles
7577
*
78+
* @deprecated -- should be rather used in policies / gates
79+
*
7680
* @return bool
7781
*/
7882
protected function hasAllRoles(array $roles): bool

src/Generator/stubs/controller.stub

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,10 @@ class {{controller.name}} extends Controller
9696
/**
9797
* Store a newly created resource in storage.
9898
* POST /api/{resource}.
99-
*
100-
* @param Request $request
99+
*
100+
* @param Request $request
101101
*
102+
* @see self::handleStoreOrUpdateAction to do magic insert / update
102103
* @return Response
103104
*/
104105
public function store(Request $request)

src/Helpers.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,18 @@ public static function filterFieldsFromRequest($request, ?array $defaultFields,
114114
*
115115
* @return array
116116
*/
117-
public static function excludeArrayValues(array $array, array $excludes, ?array $optionals = []): array
117+
public static function excludeArrayValues(array $array, array $excludes, ?array $acceptable = []): array
118118
{
119-
return Arr::where($array, function ($value) use ($excludes, $optionals) {
120-
return ! in_array($value, $excludes) || in_array($value, $optionals);
119+
return Arr::where($array, function ($value) use ($excludes, $acceptable) {
120+
if (in_array($value, $excludes)) {
121+
return false;
122+
}
123+
124+
if (! empty($acceptable)) {
125+
return in_array($value, $acceptable);
126+
}
127+
128+
return true;
121129
});
122130
}
123131
}

src/Http/Controllers/Api/Controller.php

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,9 @@ public function __construct()
105105
*
106106
* @param \Illuminate\Http\Request|\Illuminate\Foundation\Http\FormRequest $request
107107
*/
108-
public function handleIndexAction($request)
108+
public function handleIndexAction($request, array $extraParams = [])
109109
{
110+
$this->addCustomParams($request, $extraParams);
110111
$this->validateRequestType($request);
111112
$this->authoriseUserAction('viewAny');
112113
$this->getUriParser($request);
@@ -124,14 +125,23 @@ public function handleIndexAction($request)
124125
return $this->respondWithMany($items);
125126
}
126127

128+
public function handleStoreOrUpdateAction($request, array $extraParams = [])
129+
{
130+
$key = self::$model->getKeyName();
131+
$id = $request->input($key, null) ?? data_get($extraParams, $key, null);
132+
133+
return $id ? $this->handleUpdateAction($id, $request, $extraParams) : $this->handleStoreAction($request, $extraParams);
134+
}
135+
127136
/**
128137
* Store a newly created resource in storage.
129138
* POST /api/{resource}.
130139
*
131140
* @param \Illuminate\Http\Request|\Illuminate\Foundation\Http\FormRequest $request
132141
*/
133-
public function handleStoreAction($request)
142+
public function handleStoreAction($request, array $extraParams = [])
134143
{
144+
$this->addCustomParams($request, $extraParams);
135145
$this->validateRequestType($request);
136146
$this->authoriseUserAction('create');
137147

@@ -168,7 +178,7 @@ public function handleStoreAction($request)
168178
} catch (\Illuminate\Database\QueryException $exception) {
169179
$message = config('app.debug') ? $exception->getMessage() : 'Failed to create Record';
170180

171-
throw new ApiException($message);
181+
throw new ApiException($message, $exception->getCode(), $exception);
172182
} catch (\Exception $exception) {
173183
DB::rollback();
174184

@@ -183,8 +193,9 @@ public function handleStoreAction($request)
183193
* @param int $id
184194
* @param \Illuminate\Http\Request|\Illuminate\Foundation\Http\FormRequest $request
185195
*/
186-
public function handleShowAction($id, $request)
196+
public function handleShowAction($id, $request, array $extraParams = [])
187197
{
198+
$this->addCustomParams($request, $extraParams);
188199
$this->validateRequestType($request);
189200

190201
$this->authoriseUserAction('view', self::$model::find($id));
@@ -212,8 +223,9 @@ public function handleShowAction($id, $request)
212223
* @param int $id
213224
* @param \Illuminate\Http\Request|\Illuminate\Foundation\Http\FormRequest $request
214225
*/
215-
public function handleUpdateAction($id, $request)
226+
public function handleUpdateAction($id, $request, array $extraParams = [])
216227
{
228+
$this->addCustomParams($request, $extraParams);
217229
$this->validateRequestType($request);
218230

219231
$this->authoriseUserAction('update', self::$model::find($id));
@@ -260,7 +272,7 @@ public function handleUpdateAction($id, $request)
260272
} catch (\Illuminate\Database\QueryException $exception) {
261273
$message = config('app.debug') ? $exception->getMessage() : 'Failed to update Record';
262274

263-
throw new ApiException($message);
275+
throw new ApiException($message, $exception->getCode(), $exception);
264276
} catch (\Exception $exception) {
265277
DB::rollback();
266278

tests/LaravelApiHelpersTest.php

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
namespace Phpsa\LaravelApiController\Tests;
4+
5+
use Orchestra\Testbench\TestCase;
6+
use Phpsa\LaravelApiController\Facades\LaravelApiController;
7+
use Phpsa\LaravelApiController\Helpers;
8+
use Phpsa\LaravelApiController\ServiceProvider;
9+
10+
class LaravelApiHelpersTest extends TestCase
11+
{
12+
protected function getPackageProviders($app)
13+
{
14+
return [ServiceProvider::class];
15+
}
16+
17+
protected function getPackageAliases($app)
18+
{
19+
return [
20+
'laravel-api-controller' => LaravelApiController::class,
21+
];
22+
}
23+
24+
public function testSnakeCasing()
25+
{
26+
$array = [
27+
'test_one' => 'test_one',
28+
'testTwo' => 'test_two',
29+
];
30+
31+
$transposed = Helpers::snakeCaseArrayKeys($array);
32+
33+
$this->assertSame(array_keys($transposed), array_values($array));
34+
}
35+
36+
public function testCamelCasing()
37+
{
38+
$array = [
39+
'test_one' => 'testOne',
40+
'testTwo' => 'testTwo',
41+
];
42+
43+
$transposed = Helpers::camelCaseArrayKeys($array);
44+
45+
$this->assertSame(array_keys($transposed), array_values($array));
46+
}
47+
48+
public function testArrayExcludes()
49+
{
50+
$allowedFields = [
51+
'field1',
52+
'field2',
53+
'field3',
54+
'field4',
55+
'field5',
56+
];
57+
58+
$excludeFields = [
59+
'field2',
60+
];
61+
62+
$inputData = [
63+
'field1',
64+
'field2',
65+
'field3',
66+
'field4',
67+
'field5',
68+
'field6',
69+
];
70+
71+
$remaining = Helpers::excludeArrayValues($inputData, $excludeFields, $allowedFields);
72+
73+
$this->assertSame([
74+
'field1',
75+
'field3',
76+
'field4',
77+
'field5',
78+
], array_values($remaining));
79+
80+
$remaining = Helpers::excludeArrayValues($inputData, [], $allowedFields);
81+
82+
$this->assertSame([
83+
'field1',
84+
'field2',
85+
'field3',
86+
'field4',
87+
'field5',
88+
], array_values($remaining));
89+
}
90+
}

0 commit comments

Comments
 (0)