Skip to content

Commit 724ebd4

Browse files
Merge pull request #119 from MarcinOrlowski/dev
Release v6.3.2
2 parents 7a440c7 + 5d61783 commit 724ebd4

File tree

15 files changed

+279
-114
lines changed

15 files changed

+279
-114
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ env:
2323
- LARAVEL_VERSION="6.2"
2424
- LARAVEL_VERSION="6.3"
2525
- LARAVEL_VERSION="6.4"
26+
- LARAVEL_VERSION="6.5"
2627

2728
#matrix:
2829
# exclude:

CHANGES.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ See [compatibility docs](docs/compatibility.md) for details about backward compa
66

77
## CHANGE LOG ##
88

9-
* 6.3.1 (2019-11-06)
9+
* v6.3.2 (2019-11-07)
10+
* Added `ResponseBuilder::successWithMessage()` method.
11+
* Entries in `classes` config array can now have `pri` (default 0) to enforce order while
12+
merging config with built-in configuration.
13+
* Persian translation (Thanks to @FaridAghili).
14+
* Added Laravel 6.5 to Travis-CI unit tests.
15+
16+
* v6.3.1 (2019-11-06)
1017
* Fixed config merging helper causing certain user settings to be lost.
1118
* No longer exposes exception class name for message-less exceptions. Fixes #107
1219
* Added test ensuring that user privided config overshadows built-in params.

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "marcin-orlowski/laravel-api-response-builder",
33
"description": "Helps building nice, normalized and easy to consume Laravel REST API.",
44
"homepage": "https://github.com/MarcinOrlowski/laravel-api-response-builder",
5-
"version": "6.3.1",
5+
"version": "6.3.2",
66
"keywords": [
77
"laravel",
88
"json",

config/response_builder.php

Lines changed: 73 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -12,65 +12,69 @@
1212
*/
1313

1414
return [
15-
/*
16-
|-----------------------------------------------------------------------------------------------------------
17-
| Code range settings
18-
|-----------------------------------------------------------------------------------------------------------
19-
*/
20-
'min_code' => 100,
21-
'max_code' => 1024,
15+
/*
16+
|-----------------------------------------------------------------------------------------------------------
17+
| Code range settings
18+
|-----------------------------------------------------------------------------------------------------------
19+
*/
20+
'min_code' => 100,
21+
'max_code' => 1024,
2222

23-
/*
24-
|-----------------------------------------------------------------------------------------------------------
25-
| Error code to message mapping
26-
|-----------------------------------------------------------------------------------------------------------
27-
|
28-
*/
29-
'map' => [
23+
/*
24+
|-----------------------------------------------------------------------------------------------------------
25+
| Error code to message mapping
26+
|-----------------------------------------------------------------------------------------------------------
27+
|
28+
*/
29+
'map' => [
3030

31-
],
31+
],
3232

33-
/*
34-
|-----------------------------------------------------------------------------------------------------------
35-
| Response Builder classes
36-
|-----------------------------------------------------------------------------------------------------------
37-
|
38-
*/
39-
'classes' => [
40-
\Illuminate\Database\Eloquent\Model::class => [
41-
'key' => 'item',
42-
'method' => 'toArray',
43-
],
44-
\Illuminate\Support\Collection::class => [
45-
'key' => 'items',
46-
'method' => 'toArray',
47-
],
48-
\Illuminate\Database\Eloquent\Collection::class => [
49-
'key' => 'items',
50-
'method' => 'toArray',
51-
],
52-
\Illuminate\Http\Resources\Json\JsonResource::class => [
53-
'key' => 'item',
54-
'method' => 'toArray',
55-
],
56-
],
33+
/*
34+
|-----------------------------------------------------------------------------------------------------------
35+
| Response Builder classes
36+
|-----------------------------------------------------------------------------------------------------------
37+
|
38+
*/
39+
'classes' => [
40+
\Illuminate\Database\Eloquent\Model::class => [
41+
'key' => 'item',
42+
'method' => 'toArray',
43+
'pri' => 0,
44+
],
45+
\Illuminate\Support\Collection::class => [
46+
'key' => 'items',
47+
'method' => 'toArray',
48+
'pri' => -1,
49+
],
50+
\Illuminate\Database\Eloquent\Collection::class => [
51+
'key' => 'items',
52+
'method' => 'toArray',
53+
'pri' => 0,
54+
],
55+
\Illuminate\Http\Resources\Json\JsonResource::class => [
56+
'key' => 'item',
57+
'method' => 'toArray',
58+
'pri' => 0,
59+
],
60+
],
5761

58-
/*
59-
|-----------------------------------------------------------------------------------------------------------
60-
| data-to-json encoding options
61-
|-----------------------------------------------------------------------------------------------------------
62-
|
63-
*/
64-
'encoding_options' => JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_UNESCAPED_UNICODE,
62+
/*
63+
|-----------------------------------------------------------------------------------------------------------
64+
| data-to-json encoding options
65+
|-----------------------------------------------------------------------------------------------------------
66+
|
67+
*/
68+
'encoding_options' => JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_UNESCAPED_UNICODE,
6569

66-
/*
67-
|-----------------------------------------------------------------------------------------------------------
68-
| Exception handler error codes
69-
|-----------------------------------------------------------------------------------------------------------
70-
|
71-
*/
72-
'exception_handler' => [
73-
'exception' => [
70+
/*
71+
|-----------------------------------------------------------------------------------------------------------
72+
| Exception handler error codes
73+
|-----------------------------------------------------------------------------------------------------------
74+
|
75+
*/
76+
'exception_handler' => [
77+
'exception' => [
7478
// 'http_not_found' => [
7579
// 'code' => \App\ApiCodes::HTTP_NOT_FOUND(),
7680
// 'http_code' => Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST,
@@ -95,21 +99,21 @@
9599
// 'code' => \App\ApiCodes::VALIDATION_EXCEPTION(),
96100
// 'http_code' => Symfony\Component\HttpFoundation\Response::HTTP_UNPROCESSABLE_ENTITY,
97101
// ],
98-
],
99-
],
102+
],
103+
],
100104

101-
/*
102-
|-----------------------------------------------------------------------------------------------------------
103-
| Debug config
104-
|-----------------------------------------------------------------------------------------------------------
105-
|
106-
*/
107-
'debug' => [
108-
'debug_key' => 'debug',
109-
'exception_handler' => [
110-
'trace_key' => 'trace',
111-
'trace_enabled' => env('APP_DEBUG', false),
112-
],
113-
],
105+
/*
106+
|-----------------------------------------------------------------------------------------------------------
107+
| Debug config
108+
|-----------------------------------------------------------------------------------------------------------
109+
|
110+
*/
111+
'debug' => [
112+
'debug_key' => 'debug',
113+
'exception_handler' => [
114+
'trace_key' => 'trace',
115+
'trace_enabled' => env('APP_DEBUG', false),
116+
],
117+
],
114118

115119
];

docs/config.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ The entry key is a class name to check passed `data` object against, and configu
3232
Namespace\Classname::class => [
3333
'method' => 'toArray',
3434
'key' => 'items',
35+
'pri' => 0,
3536
],
3637
],
3738
```

src/Converter.php

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* @link https://github.com/MarcinOrlowski/laravel-api-response-builder
1515
*/
1616

17+
use Illuminate\Http\Response;
1718
use Illuminate\Support\Facades\Config;
1819

1920

@@ -34,7 +35,7 @@ class Converter
3435
*/
3536
public function __construct()
3637
{
37-
$classes = Config::get(ResponseBuilder::CONF_KEY_CLASSES) ?? [];
38+
$classes = static::getClassesMapping() ?? [];
3839
if (!is_array($classes)) {
3940
throw new \RuntimeException(
4041
sprintf('CONFIG: "classes" mapping must be an array (%s given)', gettype($classes)));
@@ -162,4 +163,39 @@ protected function convertArray(array $data): array
162163

163164
return $data;
164165
}
166+
167+
/**
168+
* Reads and validates "classes" config mapping
169+
*
170+
* @return array Classes mapping as specified in configuration or empty array if configuration found
171+
*
172+
* @throws \RuntimeException if "classes" mapping is technically invalid (i.e. not array etc).
173+
*/
174+
protected static function getClassesMapping(): ?array
175+
{
176+
$classes = Config::get(ResponseBuilder::CONF_KEY_CLASSES);
177+
178+
if ($classes !== null) {
179+
if (!is_array($classes)) {
180+
throw new \RuntimeException(
181+
sprintf('CONFIG: "classes" mapping must be an array (%s given)', gettype($classes)));
182+
}
183+
184+
$mandatory_keys = [
185+
ResponseBuilder::KEY_KEY,
186+
ResponseBuilder::KEY_METHOD,
187+
];
188+
foreach ($classes as $class_name => $class_config) {
189+
foreach ($mandatory_keys as $key_name) {
190+
if (!array_key_exists($key_name, $class_config)) {
191+
throw new \RuntimeException("CONFIG: Missing '{$key_name}' for '{$class_name}' class mapping");
192+
}
193+
}
194+
}
195+
} else {
196+
$classes = [];
197+
}
198+
199+
return $classes;
200+
}
165201
}

src/ResponseBuilder.php

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -100,40 +100,7 @@ class ResponseBuilder
100100
*/
101101
public const DEFAULT_ENCODING_OPTIONS = 271;
102102

103-
/**
104-
* Reads and validates "classes" config mapping
105-
*
106-
* @return array Classes mapping as specified in configuration or empty array if configuration found
107-
*
108-
* @throws \RuntimeException if "classes" mapping is technically invalid (i.e. not array etc).
109-
*/
110-
protected static function getClassesMapping(): ?array
111-
{
112-
$classes = Config::get(self::CONF_KEY_CLASSES);
113-
114-
if ($classes !== null) {
115-
if (!is_array($classes)) {
116-
throw new \RuntimeException(
117-
sprintf('CONFIG: "classes" mapping must be an array (%s given)', gettype($classes)));
118-
}
119-
120-
$mandatory_keys = [
121-
static::KEY_KEY,
122-
static::KEY_METHOD,
123-
];
124-
foreach ($classes as $class_name => $class_config) {
125-
foreach ($mandatory_keys as $key_name) {
126-
if (!array_key_exists($key_name, $class_config)) {
127-
throw new \RuntimeException("CONFIG: Missing '{$key_name}' for '{$class_name}' class mapping");
128-
}
129-
}
130-
}
131-
} else {
132-
$classes = [];
133-
}
134103

135-
return $classes;
136-
}
137104

138105
/**
139106
* Returns success
@@ -187,6 +154,22 @@ public static function successWithHttpCode(int $http_code = null): HttpResponse
187154
return static::buildSuccessResponse(null, BaseApiCodes::OK(), [], $http_code);
188155
}
189156

157+
/**
158+
* @param string $message Custom message to be returned as part of the response.
159+
* @param object|array|null $data Array of primitives and supported objects to be returned in 'data' node
160+
* of the JSON response, single supported object or @null if there's no
161+
* to be returned.
162+
* @param integer|null $http_code HTTP code to be used for HttpResponse sent or @null
163+
* for default DEFAULT_HTTP_CODE_OK.
164+
*
165+
* @return \Symfony\Component\HttpFoundation\Response
166+
*/
167+
public static function successWithMessage(string $message, $data = null, int $api_code = null,
168+
int $http_code = null): HttpResponse
169+
{
170+
return static::buildSuccessResponse($data, $api_code, [], $http_code, null, $message);
171+
}
172+
190173
/**
191174
* @param object|array|null $data Array of primitives and supported objects to be returned in 'data' node.
192175
* of the JSON response, single supported object or @null if there's no
@@ -204,16 +187,20 @@ public static function successWithHttpCode(int $http_code = null): HttpResponse
204187
* @throws \InvalidArgumentException Thrown when provided arguments are invalid.
205188
*/
206189
protected static function buildSuccessResponse($data = null, int $api_code = null, array $placeholders = null,
207-
int $http_code = null, int $json_opts = null): HttpResponse
190+
int $http_code = null, int $json_opts = null,
191+
$msg_or_api_code = null): HttpResponse
208192
{
209193
$http_code = $http_code ?? static::DEFAULT_HTTP_CODE_OK;
210194
$api_code = $api_code ?? BaseApiCodes::OK();
195+
$msg_or_api_code = $msg_or_api_code ?? $api_code;
211196

212197
Validator::assertInt('api_code', $api_code);
213198
Validator::assertInt('http_code', $http_code);
214199
Validator::assertIntRange('http_code', $http_code, 200, 299);
200+
Validator::assertType('msg_or_api_code', $msg_or_api_code, [Validator::TYPE_STRING,
201+
Validator::TYPE_INTEGER]);
215202

216-
return static::make(true, $api_code, $api_code, $data, $http_code, $placeholders, null, $json_opts);
203+
return static::make(true, $api_code, $msg_or_api_code, $data, $http_code, $placeholders, null, $json_opts);
217204
}
218205

219206
/**

src/ResponseBuilderServiceProvider.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,13 @@ public function boot()
6262
*/
6363
protected function mergeConfigFrom($path, $key)
6464
{
65+
$defaults = require $path;
6566
$config = $this->app['config']->get($key, []);
66-
$this->app['config']->set($key, Util::mergeConfig(require $path, $config));
67+
68+
$merged_config = Util::mergeConfig($defaults, $config);
69+
Util::sortArrayByPri($merged_config['classes']);
70+
71+
$this->app['config']->set($key, $merged_config);
6772
}
6873

6974
}

src/Util.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ final class Util
2222
* array with int).
2323
*
2424
* @param array $original Array to merge other array into. Usually default values to overwrite.
25-
* @param array $merging Array with items to be merged into $original, overriding (primitives) or merging
26-
* (arrays) entries in destination array.
25+
* @param array $merging Array with items to be merged into $original, overriding (primitives) or merging
26+
* (arrays) entries in destination array.
2727
*
2828
* @return array
2929
*
@@ -54,4 +54,20 @@ public static function mergeConfig(array $original, array $merging): array
5454
return $array;
5555
}
5656

57+
/**
58+
* Sorts array by value, assuming value is an array and contains `pri` key with integer (positive/negative)
59+
* value which is used for sorting higher -> lower priority.
60+
*
61+
* @param array &$array
62+
*/
63+
public static function sortArrayByPri(array &$array): void
64+
{
65+
// we now need to sort 'classes' node by priority
66+
uasort($array, function($array_a, $array_b) {
67+
$pri_a = $array_a['pri'] ?? 0;
68+
$pri_b = $array_b['pri'] ?? 0;
69+
70+
return $pri_b <=> $pri_a;
71+
});
72+
}
5773
}

0 commit comments

Comments
 (0)