Skip to content

Commit 6952a1d

Browse files
author
Robert Allport
authored
Merge pull request #16 from JacekAndrzejewski/feature/change-success-defaults
Implemented success response with an empty array
2 parents 4c3fb70 + f02f00a commit 6952a1d

File tree

3 files changed

+188
-18
lines changed

3 files changed

+188
-18
lines changed

README.md

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ Optionally, the trait could be imported within a base controller.
5050

5151
Returns a `404` HTTP status code, an exception object can optionally be passed.
5252

53-
#### `respondWithSuccess(array|Arrayable|JsonSerializable|null $contents = [])`
53+
#### `respondWithSuccess(array|Arrayable|JsonSerializable|null $contents = null)`
5454

55-
Returns a `200` HTTP status code
55+
Returns a `200` HTTP status code, optionally `$contents` to return as json can be passed. By default returns `['success' => true]`.
5656

5757
#### `respondOk(string $message)`
5858

@@ -70,14 +70,41 @@ Returns a `403` HTTP status code
7070

7171
Returns a `400` HTTP status code
7272

73-
#### `respondCreated(array|Arrayable|JsonSerializable|null $data = [])`
73+
#### `respondCreated(array|Arrayable|JsonSerializable|null $data = null)`
7474

7575
Returns a `201` HTTP status code, with response optional data
7676

77-
#### `respondNoContent(array|Arrayable|JsonSerializable|null $data = [])`
77+
#### `respondNoContent(array|Arrayable|JsonSerializable|null $data = null)`
7878

7979
Returns a `204` HTTP status code, with optional response data. Strictly speaking, the response body should be empty. However, functionality to optionally return data was added to handle legacy projects. Within your own projects, you can simply call the method, omitting parameters, to generate a correct `204` response i.e. `return $this->respondNoContent()`
8080

81+
#### `setDefaultSuccessResponse(?array $content = null): self`
82+
83+
Optionally, replace the default `['success' => true]` response returned by `respondWithSuccess` with `$content`. This method can be called from the constructor (to change default for all calls), a base API controller or place when required.
84+
85+
`setDefaultSuccessResponse` is a fluent method returning `$this` allows for chained methods calls:
86+
87+
```php
88+
$users = collect([10, 20, 30, 40]);
89+
90+
return $this->setDefaultSuccessResponse([])->respondWithSuccess($users);
91+
```
92+
93+
Or
94+
```php
95+
public function __construct()
96+
{
97+
$this->setDefaultSuccessResponse([]);
98+
}
99+
100+
...
101+
102+
$users = collect([10, 20, 30, 40]);
103+
104+
return $this->respondWithSuccess($users);
105+
```
106+
107+
81108
## Use with additional object types
82109

83110
In addition to a plain PHP `array`, the following data types can be passed to relevant methods:
@@ -148,4 +175,3 @@ If you discover any security related issues, please email [email protected] instea
148175
## License
149176

150177
The MIT License (MIT). Please see [License File](LICENSE) for more information.
151-

src/ApiResponseHelpers.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
trait ApiResponseHelpers
1616
{
17+
private ?array $_api_helpers_defaultSuccessData = ['success' => true];
18+
1719
/**
1820
* @param string|\Exception $message
1921
* @param string|null $key
@@ -33,17 +35,23 @@ public function respondNotFound(
3335
/**
3436
* @param array|Arrayable|JsonSerializable|null $contents
3537
*/
36-
public function respondWithSuccess($contents = []): JsonResponse
38+
public function respondWithSuccess($contents = null): JsonResponse
3739
{
38-
$contents = $this->morphToArray($contents);
40+
$contents = $this->morphToArray($contents) ?? [];
3941

4042
$data = [] === $contents
41-
? ['success' => true]
43+
? $this->_api_helpers_defaultSuccessData
4244
: $contents;
4345

4446
return $this->apiResponse($data);
4547
}
4648

49+
public function setDefaultSuccessResponse(?array $content = null): self
50+
{
51+
$this->_api_helpers_defaultSuccessData = $content ?? [];
52+
return $this;
53+
}
54+
4755
public function respondOk(string $message): JsonResponse
4856
{
4957
return $this->respondWithSuccess(['success' => $message]);
@@ -76,8 +84,9 @@ public function respondError(?string $message = null): JsonResponse
7684
/**
7785
* @param array|Arrayable|JsonSerializable|null $data
7886
*/
79-
public function respondCreated($data = []): JsonResponse
87+
public function respondCreated($data = null): JsonResponse
8088
{
89+
$data ??= [];
8190
return $this->apiResponse(
8291
$this->morphToArray($data),
8392
Response::HTTP_CREATED
@@ -111,8 +120,9 @@ public function respondTeapot(): JsonResponse
111120
/**
112121
* @param array|Arrayable|JsonSerializable|null $data
113122
*/
114-
public function respondNoContent($data = []): JsonResponse
123+
public function respondNoContent($data = null): JsonResponse
115124
{
125+
$data ??= [];
116126
$data = $this->morphToArray($data);
117127

118128
return $this->apiResponse($data, Response::HTTP_NO_CONTENT);

tests/ResponseTest.php

Lines changed: 142 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@
44

55
namespace F9Web\ApiResponseHelpers\Tests;
66

7-
use F9Web\ApiResponseHelpers;
8-
use Illuminate\Http\JsonResponse;
9-
use Symfony\Component\HttpFoundation\Response;
10-
use JsonException;
117
use DomainException;
12-
use Illuminate\Support\Collection;
8+
use F9Web\ApiResponseHelpers;
139
use F9Web\ApiResponseHelpers\Tests\Models\User;
1410
use F9Web\ApiResponseHelpers\Tests\Resources\UserResource;
15-
use Illuminate\Database\Eloquent\Collection As EloquentCollection;
11+
use Illuminate\Contracts\Support\Arrayable;
12+
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
13+
use Illuminate\Http\JsonResponse;
14+
use Illuminate\Support\Collection;
15+
use JsonException;
16+
use Symfony\Component\HttpFoundation\Response;
1617

1718
use function json_encode;
1819

@@ -35,8 +36,21 @@ public function testResponses(string $method, array $args, int $code, array $dat
3536
/** @var \Illuminate\Http\JsonResponse $response */
3637
$response = call_user_func_array([$this->service, $method], $args);
3738
self::assertInstanceOf(JsonResponse::class, $response);
38-
self::assertEquals($code, $response->getStatusCode());
39-
self::assertEquals($data, $response->getData(true));
39+
self::assertSame($code, $response->getStatusCode());
40+
self::assertSame($data, $response->getData(true));
41+
self::assertJsonStringEqualsJsonString(json_encode($data, JSON_THROW_ON_ERROR), $response->getContent());
42+
}
43+
44+
/**
45+
* @dataProvider successDefaultsDataProvider
46+
* @throws JsonException
47+
*/
48+
public function testSuccessResponseDefaults(?array $default, $args, int $code, array $data): void
49+
{
50+
$response = $this->service->setDefaultSuccessResponse($default)->respondWithSuccess($args);
51+
self::assertInstanceOf(JsonResponse::class, $response);
52+
self::assertSame($code, $response->getStatusCode());
53+
self::assertSame($data, $response->getData(true));
4054
self::assertJsonStringEqualsJsonString(json_encode($data, JSON_THROW_ON_ERROR), $response->getContent());
4155
}
4256

@@ -74,6 +88,13 @@ public function basicResponsesDataProvider(): array
7488
['success' => true],
7589
],
7690

91+
'respondWithSuccess(), null response data' => [
92+
'respondWithSuccess',
93+
[null],
94+
Response::HTTP_OK,
95+
['success' => true],
96+
],
97+
7798
'respondWithSuccess(), custom response data' => [
7899
'respondWithSuccess',
79100
[['order' => 237]],
@@ -95,6 +116,69 @@ public function basicResponsesDataProvider(): array
95116
['invoice' => 23, 'status' => 'pending'],
96117
],
97118

119+
'respondWithSuccess(), empty collection' => [
120+
'respondWithSuccess',
121+
[new Collection()],
122+
Response::HTTP_OK,
123+
['success' => true],
124+
],
125+
126+
'respondWithSuccess(), Arrayable' => [
127+
'respondWithSuccess',
128+
[
129+
new class implements Arrayable {
130+
public function toArray()
131+
{
132+
return ['id' => 1, 'name' => 'John'];
133+
}
134+
},
135+
],
136+
Response::HTTP_OK,
137+
['id' => 1, 'name' => 'John']
138+
],
139+
140+
'respondWithSuccess(), empty Arrayable' => [
141+
'respondWithSuccess',
142+
[
143+
new class implements Arrayable {
144+
public function toArray()
145+
{
146+
return [];
147+
}
148+
},
149+
],
150+
Response::HTTP_OK,
151+
['success' => true]
152+
],
153+
154+
'respondWithSuccess(), JsonSerializable' => [
155+
'respondWithSuccess',
156+
[
157+
new class implements \JsonSerializable {
158+
public function jsonSerialize()
159+
{
160+
return ['id' => 1, 'name' => 'John'];
161+
}
162+
},
163+
],
164+
Response::HTTP_OK,
165+
['id' => 1, 'name' => 'John']
166+
],
167+
168+
'respondWithSuccess(), empty JsonSerializable' => [
169+
'respondWithSuccess',
170+
[
171+
new class implements \JsonSerializable {
172+
public function jsonSerialize()
173+
{
174+
return [];
175+
}
176+
},
177+
],
178+
Response::HTTP_OK,
179+
['success' => true]
180+
],
181+
98182
'respondOk()' => [
99183
'respondOk',
100184
['Order accepted'],
@@ -151,6 +235,13 @@ public function basicResponsesDataProvider(): array
151235
[],
152236
],
153237

238+
'respondCreated() with null' => [
239+
'respondCreated',
240+
[null],
241+
Response::HTTP_CREATED,
242+
[],
243+
],
244+
154245
'respondCreated() with response data' => [
155246
'respondCreated',
156247
[['user' => ['name' => 'Jet Li']]],
@@ -233,6 +324,13 @@ public function basicResponsesDataProvider(): array
233324
[],
234325
],
235326

327+
'respondNoContent() with null' => [
328+
'respondNoContent',
329+
[null],
330+
Response::HTTP_NO_CONTENT,
331+
[],
332+
],
333+
236334
// @see https://github.com/f9webltd/laravel-api-response-helpers/issues/5#issuecomment-917418285
237335
'respondNoContent() with data' => [
238336
'respondNoContent',
@@ -250,4 +348,40 @@ public function basicResponsesDataProvider(): array
250348
],
251349
];
252350
}
351+
352+
public function successDefaultsDataProvider(): array
353+
{
354+
return [
355+
'respondWithSuccess(), default empty array' => [
356+
'default' => [],
357+
'args' => [],
358+
'code' => Response::HTTP_OK,
359+
'data' => [],
360+
],
361+
'respondWithSuccess(), default null' => [
362+
'default' => null,
363+
'args' => [],
364+
'code' => Response::HTTP_OK,
365+
'data' => [],
366+
],
367+
'respondWithSuccess(), default null, null response' => [
368+
'default' => null,
369+
'args' => null,
370+
'code' => Response::HTTP_OK,
371+
'data' => [],
372+
],
373+
'respondWithSuccess(), default non-empty array' => [
374+
'default' => ['message' => 'Task successful!'],
375+
'args' => [],
376+
'code' => Response::HTTP_OK,
377+
'data' => ['message' => 'Task successful!'],
378+
],
379+
'respondWithSuccess(), default non-empty array, custom response data' => [
380+
'default' => ['message' => 'Task successful!'],
381+
'args' => ['numbers' => [1, 2, 3]],
382+
'code' => Response::HTTP_OK,
383+
'data' => ['numbers' => [1, 2, 3]],
384+
]
385+
];
386+
}
253387
}

0 commit comments

Comments
 (0)