Passed
Push — master ( 65b5b3...7a440c )
by Marcin
07:59 queued 10s
created
src/ResponseBuilder.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -505,7 +505,7 @@  discard block
 block discarded – undo
505 505
         $data = $converter->convert($data);
506 506
         if ($data !== null && !is_object($data)) {
507 507
             // ensure we get object in final JSON structure in data node
508
-            $data = (object)$data;
508
+            $data = (object) $data;
509 509
         }
510 510
 
511 511
         // get human readable message for API code or use message string (if given instead of API code)
@@ -527,7 +527,7 @@  discard block
 block discarded – undo
527 527
 
528 528
         if ($debug_data !== null) {
529 529
             $debug_key = Config::get(static::CONF_KEY_DEBUG_DEBUG_KEY, self::KEY_DEBUG);
530
-            $response[ $debug_key ] = $debug_data;
530
+            $response[$debug_key] = $debug_data;
531 531
         }
532 532
 
533 533
         return $response;
Please login to merge, or discard this patch.
Indentation   +507 added lines, -507 removed lines patch added patch discarded remove patch
@@ -24,512 +24,512 @@
 block discarded – undo
24 24
  */
25 25
 class ResponseBuilder
26 26
 {
27
-    /**
28
-     * Default HTTP code to be used with success responses
29
-     *
30
-     * @var int
31
-     */
32
-    public const DEFAULT_HTTP_CODE_OK = HttpResponse::HTTP_OK;
33
-
34
-    /**
35
-     * Default HTTP code to be used with error responses
36
-     *
37
-     * @var int
38
-     */
39
-    public const DEFAULT_HTTP_CODE_ERROR = HttpResponse::HTTP_BAD_REQUEST;
40
-
41
-    /**
42
-     * Min allowed HTTP code for errorXXX()
43
-     *
44
-     * @var int
45
-     */
46
-    public const ERROR_HTTP_CODE_MIN = 400;
47
-
48
-    /**
49
-     * Max allowed HTTP code for errorXXX()
50
-     *
51
-     * @var int
52
-     */
53
-    public const ERROR_HTTP_CODE_MAX = 599;
54
-
55
-    /**
56
-     * Configuration keys
57
-     */
58
-    public const CONF_KEY_DEBUG_DEBUG_KEY        = 'response_builder.debug.debug_key';
59
-    public const CONF_KEY_DEBUG_EX_TRACE_ENABLED = 'response_builder.debug.exception_handler.trace_enabled';
60
-    public const CONF_KEY_DEBUG_EX_TRACE_KEY     = 'response_builder.debug.exception_handler.trace_key';
61
-    public const CONF_KEY_MAP                    = 'response_builder.map';
62
-    public const CONF_KEY_ENCODING_OPTIONS       = 'response_builder.encoding_options';
63
-    public const CONF_KEY_CLASSES                = 'response_builder.classes';
64
-    public const CONF_KEY_MIN_CODE               = 'response_builder.min_code';
65
-    public const CONF_KEY_MAX_CODE               = 'response_builder.max_code';
66
-    public const CONF_EXCEPTION_HANDLER_KEY      = 'response_builder.exception_handler';
67
-
68
-    /**
69
-     * Default keys to be used by exception handler while adding debug information
70
-     */
71
-    public const KEY_DEBUG   = 'debug';
72
-    public const KEY_TRACE   = 'trace';
73
-    public const KEY_CLASS   = 'class';
74
-    public const KEY_FILE    = 'file';
75
-    public const KEY_LINE    = 'line';
76
-    public const KEY_KEY     = 'key';
77
-    public const KEY_METHOD  = 'method';
78
-    public const KEY_SUCCESS = 'success';
79
-    public const KEY_CODE    = 'code';
80
-    public const KEY_LOCALE  = 'locale';
81
-    public const KEY_MESSAGE = 'message';
82
-    public const KEY_DATA    = 'data';
83
-
84
-    /**
85
-     * Default key to be used by exception handler while processing ValidationException
86
-     * to return all the error messages
87
-     *
88
-     * @var string
89
-     */
90
-    public const KEY_MESSAGES = 'messages';
91
-
92
-    /**
93
-     * Default JSON encoding options. Must be specified as final value (i.e. 271) and NOT
94
-     * PHP expression i.e. `JSON_HEX_TAG|JSON_HEX_APOS|...` as such syntax is not yet supported
95
-     * by PHP.
96
-     *
97
-     * 271 = JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_AMP|JSON_HEX_QUOT|JSON_UNESCAPED_UNICODE
98
-     *
99
-     * @var int
100
-     */
101
-    public const DEFAULT_ENCODING_OPTIONS = 271;
102
-
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
-        }
134
-
135
-        return $classes;
136
-    }
137
-
138
-    /**
139
-     * Returns success
140
-     *
141
-     * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
142
-     *                                         of the JSON response, single supported object or @null if there's no
143
-     *                                         to be returned.
144
-     * @param integer|null      $api_code      API code to be returned or @null to use value of BaseApiCodes::OK().
145
-     * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
146
-     *                                         substitution or @null if none.
147
-     * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
148
-     *                                         for default DEFAULT_HTTP_CODE_OK.
149
-     * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
150
-     *                                         options or pass @null to use value from your config (or defaults).
151
-     *
152
-     * @return HttpResponse
153
-     */
154
-    public static function success($data = null, $api_code = null, array $placeholders = null,
155
-                                   int $http_code = null, int $json_opts = null): HttpResponse
156
-    {
157
-        return static::buildSuccessResponse($data, $api_code, $placeholders, $http_code, $json_opts);
158
-    }
159
-
160
-    /**
161
-     * Returns success
162
-     *
163
-     * @param integer|null $api_code      API code to be returned or @null to use value of BaseApiCodes::OK().
164
-     * @param array|null   $placeholders  Placeholders passed to Lang::get() for message placeholders
165
-     *                                    substitution or @null if none.
166
-     * @param integer|null $http_code     HTTP code to be used for HttpResponse sent or @null
167
-     *                                    for default DEFAULT_HTTP_CODE_OK.
168
-     *
169
-     * @return HttpResponse
170
-     */
171
-    public static function successWithCode(int $api_code = null, array $placeholders = null,
172
-                                           int $http_code = null): HttpResponse
173
-    {
174
-        return static::success(null, $api_code, $placeholders, $http_code);
175
-    }
176
-
177
-    /**
178
-     * Returns success with custom HTTP code
179
-     *
180
-     * @param integer|null $http_code HTTP return code to be set for this response. If @null is passed, falls back
181
-     *                                to DEFAULT_HTTP_CODE_OK.
182
-     *
183
-     * @return HttpResponse
184
-     */
185
-    public static function successWithHttpCode(int $http_code = null): HttpResponse
186
-    {
187
-        return static::buildSuccessResponse(null, BaseApiCodes::OK(), [], $http_code);
188
-    }
189
-
190
-    /**
191
-     * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node.
192
-     *                                         of the JSON response, single supported object or @null if there's no
193
-     *                                         to be returned.
194
-     * @param integer|null      $api_code      API code to be returned or @null to use value of BaseApiCodes::OK().
195
-     * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
196
-     *                                         substitution or @null if none.
197
-     * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
198
-     *                                         for default DEFAULT_HTTP_CODE_OK.
199
-     * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
200
-     *                                         options or pass @null to use value from your config (or defaults).
201
-     *
202
-     * @return HttpResponse
203
-     *
204
-     * @throws \InvalidArgumentException Thrown when provided arguments are invalid.
205
-     */
206
-    protected static function buildSuccessResponse($data = null, int $api_code = null, array $placeholders = null,
207
-                                                   int $http_code = null, int $json_opts = null): HttpResponse
208
-    {
209
-        $http_code = $http_code ?? static::DEFAULT_HTTP_CODE_OK;
210
-        $api_code = $api_code ?? BaseApiCodes::OK();
211
-
212
-        Validator::assertInt('api_code', $api_code);
213
-        Validator::assertInt('http_code', $http_code);
214
-        Validator::assertIntRange('http_code', $http_code, 200, 299);
215
-
216
-        return static::make(true, $api_code, $api_code, $data, $http_code, $placeholders, null, $json_opts);
217
-    }
218
-
219
-    /**
220
-     * Builds error Response object. Supports optional arguments passed to Lang::get() if associated error
221
-     * message uses placeholders as well as return data payload
222
-     *
223
-     * @param integer           $api_code      Your API code to be returned with the response object.
224
-     * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
225
-     *                                         substitution or @null if none.
226
-     * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
227
-     *                                         of the JSON response, single supported object or @null if there's no
228
-     *                                         to be returned.
229
-     * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
230
-     *                                         for default DEFAULT_HTTP_CODE_ERROR.
231
-     * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
232
-     *                                         options or pass @null to use value from your config (or defaults).
233
-     *
234
-     * @return HttpResponse
235
-     */
236
-    public static function error(int $api_code, array $placeholders = null, $data = null, int $http_code = null,
237
-                                 int $encoding_options = null): HttpResponse
238
-    {
239
-        return static::buildErrorResponse($data, $api_code, $http_code, $placeholders, $encoding_options);
240
-    }
241
-
242
-    /**
243
-     * @param integer           $api_code      Your API code to be returned with the response object.
244
-     * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
245
-     *                                         of the JSON response, single supported object or @null if there's no
246
-     *                                         to be returned.
247
-     * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
248
-     *                                         substitution or @null if none.
249
-     * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
250
-     *                                         options or pass @null to use value from your config (or defaults).
251
-     *
252
-     * @return HttpResponse
253
-     */
254
-    public static function errorWithData(int $api_code, $data, array $placeholders = null,
255
-                                         int $json_opts = null): HttpResponse
256
-    {
257
-        return static::buildErrorResponse($data, $api_code, null, $placeholders, $json_opts);
258
-    }
259
-
260
-    /**
261
-     * @param integer           $api_code      Your API code to be returned with the response object.
262
-     * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
263
-     *                                         of the JSON response, single supported object or @null if there's no
264
-     *                                         to be returned.
265
-     * @param integer           $http_code     HTTP code to be used for HttpResponse sent.
266
-     * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
267
-     *                                         substitution or @null if none.
268
-     * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
269
-     *                                         options or pass @null to use value from your config (or defaults).
270
-     *
271
-     * @return HttpResponse
272
-     *
273
-     * @throws \InvalidArgumentException if http_code is @null
274
-     */
275
-    public static function errorWithDataAndHttpCode(int $api_code, $data, int $http_code, array $placeholders = null,
276
-                                                    int $json_opts = null): HttpResponse
277
-    {
278
-        return static::buildErrorResponse($data, $api_code, $http_code, $placeholders, $json_opts);
279
-    }
280
-
281
-    /**
282
-     * @param integer    $api_code     Your API code to be returned with the response object.
283
-     * @param integer    $http_code    HTTP code to be used for HttpResponse sent or @null
284
-     *                                 for default DEFAULT_HTTP_CODE_ERROR.
285
-     * @param array|null $placeholders Placeholders passed to Lang::get() for message placeholders
286
-     *                                 substitution or @null if none.
287
-     *
288
-     * @return HttpResponse
289
-     *
290
-     * @throws \InvalidArgumentException if http_code is @null
291
-     */
292
-    public static function errorWithHttpCode(int $api_code, int $http_code, array $placeholders = null): HttpResponse
293
-    {
294
-        return static::buildErrorResponse(null, $api_code, $http_code, $placeholders);
295
-    }
296
-
297
-    /**
298
-     * @param integer           $api_code  Your API code to be returned with the response object.
299
-     * @param string            $message   Custom message to be returned as part of error response
300
-     * @param object|array|null $data      Array of primitives and supported objects to be returned in 'data' node
301
-     *                                     of the JSON response, single supported object or @null if there's no
302
-     *                                     to be returned.
303
-     * @param integer|null      $http_code Optional HTTP status code to be used for HttpResponse sent
304
-     *                                     or @null for DEFAULT_HTTP_CODE_ERROR
305
-     * @param integer|null      $json_opts See http://php.net/manual/en/function.json-encode.php for supported
306
-     *                                     options or pass @null to use value from your config (or defaults).
307
-     *
308
-     * @return HttpResponse
309
-     */
310
-    public static function errorWithMessageAndData(int $api_code, string $message, $data,
311
-                                                   int $http_code = null, int $json_opts = null): HttpResponse
312
-    {
313
-        return static::buildErrorResponse($data, $api_code, $http_code, null,
314
-            $message, null, $json_opts);
315
-    }
316
-
317
-    /**
318
-     * @param integer           $api_code   Your API code to be returned with the response object.
319
-     * @param string            $message    custom message to be returned as part of error response
320
-     * @param object|array|null $data       Array of primitives and supported objects to be returned in 'data' node
321
-     *                                      of the JSON response, single supported object or @null if there's no
322
-     *                                      to be returned.
323
-     * @param integer|null      $http_code  HTTP code to be used for HttpResponse sent or @null
324
-     *                                      for default DEFAULT_HTTP_CODE_ERROR.
325
-     * @param integer|null      $json_opts  See http://php.net/manual/en/function.json-encode.php for supported
326
-     *                                      options or pass @null to use value from your config (or defaults).
327
-     * @param array|null        $debug_data optional debug data array to be added to returned JSON.
328
-     *
329
-     * @return HttpResponse
330
-     */
331
-    public static function errorWithMessageAndDataAndDebug(int $api_code, string $message, $data,
332
-                                                           int $http_code = null, int $json_opts = null,
333
-                                                           array $debug_data = null): HttpResponse
334
-    {
335
-        return static::buildErrorResponse($data, $api_code, $http_code, null,
336
-            $message, null, $json_opts, $debug_data);
337
-    }
338
-
339
-    /**
340
-     * @param integer      $api_code  Your API code to be returned with the response object.
341
-     * @param string       $message   Custom message to be returned as part of error response
342
-     * @param integer|null $http_code HTTP code to be used with final response sent or @null
343
-     *                                for default DEFAULT_HTTP_CODE_ERROR.
344
-     *
345
-     * @return HttpResponse
346
-     */
347
-    public static function errorWithMessage(int $api_code, string $message, int $http_code = null): HttpResponse
348
-    {
349
-        return static::buildErrorResponse(null, $api_code, $http_code, null, $message);
350
-    }
351
-
352
-    /**
353
-     * Builds error Response object. Supports optional arguments passed to Lang::get() if associated error message
354
-     * uses placeholders as well as return data payload
355
-     *
356
-     * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
357
-     *                                         of the JSON response, single supported object or @null if there's no
358
-     *                                         to be returned.
359
-     * @param integer           $api_code      Your API code to be returned with the response object.
360
-     * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
361
-     *                                         for default DEFAULT_HTTP_CODE_ERROR.
362
-     * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
363
-     *                                         substitution or @null if none.
364
-     * @param string|null       $message       custom message to be returned as part of error response
365
-     * @param array|null        $headers       optional HTTP headers to be returned in error response
366
-     * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
367
-     *                                         options or pass @null to use value from your config (or defaults).
368
-     * @param array|null        $debug_data    optional debug data array to be added to returned JSON.
369
-     *
370
-     * @return HttpResponse
371
-     *
372
-     * @throws \InvalidArgumentException Thrown if $code is not correct, outside the range, equals OK code etc.
373
-     *
374
-     * @noinspection MoreThanThreeArgumentsInspection
375
-     */
376
-    protected static function buildErrorResponse($data, int $api_code, int $http_code = null,
377
-                                                 array $placeholders = null,
378
-                                                 string $message = null, array $headers = null,
379
-                                                 int $json_opts = null,
380
-                                                 array $debug_data = null): HttpResponse
381
-    {
382
-        $http_code = $http_code ?? static::DEFAULT_HTTP_CODE_ERROR;
383
-        $headers = $headers ?? [];
384
-
385
-        Validator::assertInt('api_code', $api_code);
386
-
387
-        $code_ok = BaseApiCodes::OK();
388
-        if ($api_code !== $code_ok) {
389
-            Validator::assertIntRange('api_code', $api_code, BaseApiCodes::getMinCode(), BaseApiCodes::getMaxCode());
390
-        }
391
-        if ($api_code === $code_ok) {
392
-            throw new \InvalidArgumentException(
393
-                "Error response cannot use api_code of value  {$code_ok} which is reserved for OK");
394
-        }
395
-
396
-        Validator::assertInt('http_code', $http_code);
397
-        Validator::assertIntRange('http_code', $http_code, static::ERROR_HTTP_CODE_MIN, static::ERROR_HTTP_CODE_MAX);
398
-
399
-        $msg_or_api_code = $message ?? $api_code;
400
-
401
-        return static::make(false, $api_code, $msg_or_api_code, $data, $http_code,
402
-            $placeholders, $headers, $json_opts, $debug_data);
403
-    }
404
-
405
-    /**
406
-     * @param boolean           $success         @true if response reports successful operation, @false otherwise.
407
-     * @param integer           $api_code        Your API code to be returned with the response object.
408
-     * @param string|integer    $msg_or_api_code message string or valid API code to get message for
409
-     * @param object|array|null $data            optional additional data to be included in response object
410
-     * @param integer|null      $http_code       HTTP code for the HttpResponse or @null for either DEFAULT_HTTP_CODE_OK
411
-     *                                           or DEFAULT_HTTP_CODE_ERROR depending on the $success.
412
-     * @param array|null        $placeholders    Placeholders passed to Lang::get() for message placeholders
413
-     *                                           substitution or @null if none.
414
-     * @param array|null        $headers         Optional HTTP headers to be returned in the response.
415
-     * @param integer|null      $json_opts       See http://php.net/manual/en/function.json-encode.php for supported
416
-     *                                           options or pass @null to use value from your config (or defaults).
417
-     * @param array|null        $debug_data      Optional debug data array to be added to returned JSON.
418
-     *
419
-     * @return HttpResponse
420
-     *
421
-     * @throws \InvalidArgumentException If $api_code is neither a string nor valid integer code.
422
-     * @throws \InvalidArgumentException if $data is an object of class that is not configured in "classes" mapping.
423
-     *
424
-     * @noinspection MoreThanThreeArgumentsInspection
425
-     */
426
-    protected static function make(bool $success, int $api_code, $msg_or_api_code, $data = null,
427
-                                   int $http_code = null, array $placeholders = null, array $headers = null,
428
-                                   int $json_opts = null, array $debug_data = null): HttpResponse
429
-    {
430
-        $headers = $headers ?? [];
431
-        $http_code = $http_code ?? ($success ? static::DEFAULT_HTTP_CODE_OK : static::DEFAULT_HTTP_CODE_ERROR);
432
-        $json_opts = $json_opts ?? Config::get(self::CONF_KEY_ENCODING_OPTIONS, static::DEFAULT_ENCODING_OPTIONS);
433
-
434
-        Validator::assertInt('encoding_options', $json_opts);
435
-
436
-        Validator::assertInt('api_code', $api_code);
437
-        if (!BaseApiCodes::isCodeValid($api_code)) {
438
-            $min = BaseApiCodes::getMinCode();
439
-            $max = BaseApiCodes::getMaxCode();
440
-            throw new \InvalidArgumentException("API code value ({$api_code}) is out of allowed range {$min}-{$max}");
441
-        }
442
-
443
-        return Response::json(
444
-            static::buildResponse($success, $api_code, $msg_or_api_code, $placeholders, $data, $debug_data),
445
-            $http_code, $headers, $json_opts);
446
-    }
447
-
448
-    /**
449
-     * If $msg_or_api_code is integer value, returns human readable message associated with that code (with
450
-     * fallback to built-in default string if no api code mapping is set. If $msg_or_api_code is a string,
451
-     * returns it unaltered.
452
-     *
453
-     * @param boolean    $success      @true if response reports successful operation, @false otherwise.
454
-     * @param integer    $api_code     Your API code to be returned with the response object.
455
-     * @param array|null $placeholders Placeholders passed to Lang::get() for message placeholders
456
-     *                                 substitution or @null if none.
457
-     *
458
-     * @return string
459
-     */
460
-    protected static function getMessageForApiCode(bool $success, int $api_code, array $placeholders = null): string
461
-    {
462
-        // We got integer value here not a message string, so we need to check if we have the mapping for
463
-        // this string already configured.
464
-        $key = BaseApiCodes::getCodeMessageKey($api_code);
465
-        if ($key === null) {
466
-            // nope, let's get the default one instead, based of
467
-            $fallback_code = $success ? BaseApiCodes::OK() : BaseApiCodes::NO_ERROR_MESSAGE();
468
-            $key = BaseApiCodes::getCodeMessageKey($fallback_code);
469
-        }
470
-
471
-        $placeholders = $placeholders ?? [];
472
-        if (!array_key_exists('api_code', $placeholders)) {
473
-            $placeholders['api_code'] = $api_code;
474
-        }
475
-
476
-        return \Lang::get($key, $placeholders);
477
-    }
478
-
479
-    /**
480
-     * Creates standardised API response array. This is final method called in the whole pipeline before we
481
-     * return final JSON back to client. If you want to manipulate your response, this is the place to do that.
482
-     * If you set APP_DEBUG to true, 'code_hex' field will be additionally added to reported JSON for easier
483
-     * manual debugging.
484
-     *
485
-     * @param boolean           $success         @true if response reports successful operation, @false otherwise.
486
-     * @param integer           $api_code        Your API code to be returned with the response object.
487
-     * @param string|integer    $msg_or_api_code Message string or valid API code to get message for.
488
-     * @param array|null        $placeholders    Placeholders passed to Lang::get() for message placeholders
489
-     *                                           substitution or @null if none.
490
-     * @param object|array|null $data            API response data if any
491
-     * @param array|null        $debug_data      optional debug data array to be added to returned JSON.
492
-     *
493
-     * @return array response ready to be encoded as json and sent back to client
494
-     *
495
-     * @throws \RuntimeException in case of missing or invalid "classes" mapping configuration
496
-     */
497
-    protected static function buildResponse(bool $success, int $api_code,
498
-                                            $msg_or_api_code, array $placeholders = null,
499
-                                            $data = null, array $debug_data = null): array
500
-    {
501
-        // ensure $data is either @null, array or object of class with configured mapping.
502
-        $converter = new Converter();
503
-
504
-        $data = $converter->convert($data);
505
-        if ($data !== null && !is_object($data)) {
506
-            // ensure we get object in final JSON structure in data node
507
-            $data = (object)$data;
508
-        }
509
-
510
-        // get human readable message for API code or use message string (if given instead of API code)
511
-        if (is_int($msg_or_api_code)) {
512
-            $message = self::getMessageForApiCode($success, $msg_or_api_code, $placeholders);
513
-        } else {
514
-            Validator::assertString('message', $msg_or_api_code);
515
-            $message = $msg_or_api_code;
516
-        }
517
-
518
-        /** @noinspection PhpUndefinedClassInspection */
519
-        $response = [
520
-            static::KEY_SUCCESS => $success,
521
-            static::KEY_CODE    => $api_code,
522
-            static::KEY_LOCALE  => \App::getLocale(),
523
-            static::KEY_MESSAGE => $message,
524
-            static::KEY_DATA    => $data,
525
-        ];
526
-
527
-        if ($debug_data !== null) {
528
-            $debug_key = Config::get(static::CONF_KEY_DEBUG_DEBUG_KEY, self::KEY_DEBUG);
529
-            $response[ $debug_key ] = $debug_data;
530
-        }
531
-
532
-        return $response;
533
-    }
27
+	/**
28
+	 * Default HTTP code to be used with success responses
29
+	 *
30
+	 * @var int
31
+	 */
32
+	public const DEFAULT_HTTP_CODE_OK = HttpResponse::HTTP_OK;
33
+
34
+	/**
35
+	 * Default HTTP code to be used with error responses
36
+	 *
37
+	 * @var int
38
+	 */
39
+	public const DEFAULT_HTTP_CODE_ERROR = HttpResponse::HTTP_BAD_REQUEST;
40
+
41
+	/**
42
+	 * Min allowed HTTP code for errorXXX()
43
+	 *
44
+	 * @var int
45
+	 */
46
+	public const ERROR_HTTP_CODE_MIN = 400;
47
+
48
+	/**
49
+	 * Max allowed HTTP code for errorXXX()
50
+	 *
51
+	 * @var int
52
+	 */
53
+	public const ERROR_HTTP_CODE_MAX = 599;
54
+
55
+	/**
56
+	 * Configuration keys
57
+	 */
58
+	public const CONF_KEY_DEBUG_DEBUG_KEY        = 'response_builder.debug.debug_key';
59
+	public const CONF_KEY_DEBUG_EX_TRACE_ENABLED = 'response_builder.debug.exception_handler.trace_enabled';
60
+	public const CONF_KEY_DEBUG_EX_TRACE_KEY     = 'response_builder.debug.exception_handler.trace_key';
61
+	public const CONF_KEY_MAP                    = 'response_builder.map';
62
+	public const CONF_KEY_ENCODING_OPTIONS       = 'response_builder.encoding_options';
63
+	public const CONF_KEY_CLASSES                = 'response_builder.classes';
64
+	public const CONF_KEY_MIN_CODE               = 'response_builder.min_code';
65
+	public const CONF_KEY_MAX_CODE               = 'response_builder.max_code';
66
+	public const CONF_EXCEPTION_HANDLER_KEY      = 'response_builder.exception_handler';
67
+
68
+	/**
69
+	 * Default keys to be used by exception handler while adding debug information
70
+	 */
71
+	public const KEY_DEBUG   = 'debug';
72
+	public const KEY_TRACE   = 'trace';
73
+	public const KEY_CLASS   = 'class';
74
+	public const KEY_FILE    = 'file';
75
+	public const KEY_LINE    = 'line';
76
+	public const KEY_KEY     = 'key';
77
+	public const KEY_METHOD  = 'method';
78
+	public const KEY_SUCCESS = 'success';
79
+	public const KEY_CODE    = 'code';
80
+	public const KEY_LOCALE  = 'locale';
81
+	public const KEY_MESSAGE = 'message';
82
+	public const KEY_DATA    = 'data';
83
+
84
+	/**
85
+	 * Default key to be used by exception handler while processing ValidationException
86
+	 * to return all the error messages
87
+	 *
88
+	 * @var string
89
+	 */
90
+	public const KEY_MESSAGES = 'messages';
91
+
92
+	/**
93
+	 * Default JSON encoding options. Must be specified as final value (i.e. 271) and NOT
94
+	 * PHP expression i.e. `JSON_HEX_TAG|JSON_HEX_APOS|...` as such syntax is not yet supported
95
+	 * by PHP.
96
+	 *
97
+	 * 271 = JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_AMP|JSON_HEX_QUOT|JSON_UNESCAPED_UNICODE
98
+	 *
99
+	 * @var int
100
+	 */
101
+	public const DEFAULT_ENCODING_OPTIONS = 271;
102
+
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
+		}
134
+
135
+		return $classes;
136
+	}
137
+
138
+	/**
139
+	 * Returns success
140
+	 *
141
+	 * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
142
+	 *                                         of the JSON response, single supported object or @null if there's no
143
+	 *                                         to be returned.
144
+	 * @param integer|null      $api_code      API code to be returned or @null to use value of BaseApiCodes::OK().
145
+	 * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
146
+	 *                                         substitution or @null if none.
147
+	 * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
148
+	 *                                         for default DEFAULT_HTTP_CODE_OK.
149
+	 * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
150
+	 *                                         options or pass @null to use value from your config (or defaults).
151
+	 *
152
+	 * @return HttpResponse
153
+	 */
154
+	public static function success($data = null, $api_code = null, array $placeholders = null,
155
+								   int $http_code = null, int $json_opts = null): HttpResponse
156
+	{
157
+		return static::buildSuccessResponse($data, $api_code, $placeholders, $http_code, $json_opts);
158
+	}
159
+
160
+	/**
161
+	 * Returns success
162
+	 *
163
+	 * @param integer|null $api_code      API code to be returned or @null to use value of BaseApiCodes::OK().
164
+	 * @param array|null   $placeholders  Placeholders passed to Lang::get() for message placeholders
165
+	 *                                    substitution or @null if none.
166
+	 * @param integer|null $http_code     HTTP code to be used for HttpResponse sent or @null
167
+	 *                                    for default DEFAULT_HTTP_CODE_OK.
168
+	 *
169
+	 * @return HttpResponse
170
+	 */
171
+	public static function successWithCode(int $api_code = null, array $placeholders = null,
172
+										   int $http_code = null): HttpResponse
173
+	{
174
+		return static::success(null, $api_code, $placeholders, $http_code);
175
+	}
176
+
177
+	/**
178
+	 * Returns success with custom HTTP code
179
+	 *
180
+	 * @param integer|null $http_code HTTP return code to be set for this response. If @null is passed, falls back
181
+	 *                                to DEFAULT_HTTP_CODE_OK.
182
+	 *
183
+	 * @return HttpResponse
184
+	 */
185
+	public static function successWithHttpCode(int $http_code = null): HttpResponse
186
+	{
187
+		return static::buildSuccessResponse(null, BaseApiCodes::OK(), [], $http_code);
188
+	}
189
+
190
+	/**
191
+	 * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node.
192
+	 *                                         of the JSON response, single supported object or @null if there's no
193
+	 *                                         to be returned.
194
+	 * @param integer|null      $api_code      API code to be returned or @null to use value of BaseApiCodes::OK().
195
+	 * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
196
+	 *                                         substitution or @null if none.
197
+	 * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
198
+	 *                                         for default DEFAULT_HTTP_CODE_OK.
199
+	 * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
200
+	 *                                         options or pass @null to use value from your config (or defaults).
201
+	 *
202
+	 * @return HttpResponse
203
+	 *
204
+	 * @throws \InvalidArgumentException Thrown when provided arguments are invalid.
205
+	 */
206
+	protected static function buildSuccessResponse($data = null, int $api_code = null, array $placeholders = null,
207
+												   int $http_code = null, int $json_opts = null): HttpResponse
208
+	{
209
+		$http_code = $http_code ?? static::DEFAULT_HTTP_CODE_OK;
210
+		$api_code = $api_code ?? BaseApiCodes::OK();
211
+
212
+		Validator::assertInt('api_code', $api_code);
213
+		Validator::assertInt('http_code', $http_code);
214
+		Validator::assertIntRange('http_code', $http_code, 200, 299);
215
+
216
+		return static::make(true, $api_code, $api_code, $data, $http_code, $placeholders, null, $json_opts);
217
+	}
218
+
219
+	/**
220
+	 * Builds error Response object. Supports optional arguments passed to Lang::get() if associated error
221
+	 * message uses placeholders as well as return data payload
222
+	 *
223
+	 * @param integer           $api_code      Your API code to be returned with the response object.
224
+	 * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
225
+	 *                                         substitution or @null if none.
226
+	 * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
227
+	 *                                         of the JSON response, single supported object or @null if there's no
228
+	 *                                         to be returned.
229
+	 * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
230
+	 *                                         for default DEFAULT_HTTP_CODE_ERROR.
231
+	 * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
232
+	 *                                         options or pass @null to use value from your config (or defaults).
233
+	 *
234
+	 * @return HttpResponse
235
+	 */
236
+	public static function error(int $api_code, array $placeholders = null, $data = null, int $http_code = null,
237
+								 int $encoding_options = null): HttpResponse
238
+	{
239
+		return static::buildErrorResponse($data, $api_code, $http_code, $placeholders, $encoding_options);
240
+	}
241
+
242
+	/**
243
+	 * @param integer           $api_code      Your API code to be returned with the response object.
244
+	 * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
245
+	 *                                         of the JSON response, single supported object or @null if there's no
246
+	 *                                         to be returned.
247
+	 * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
248
+	 *                                         substitution or @null if none.
249
+	 * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
250
+	 *                                         options or pass @null to use value from your config (or defaults).
251
+	 *
252
+	 * @return HttpResponse
253
+	 */
254
+	public static function errorWithData(int $api_code, $data, array $placeholders = null,
255
+										 int $json_opts = null): HttpResponse
256
+	{
257
+		return static::buildErrorResponse($data, $api_code, null, $placeholders, $json_opts);
258
+	}
259
+
260
+	/**
261
+	 * @param integer           $api_code      Your API code to be returned with the response object.
262
+	 * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
263
+	 *                                         of the JSON response, single supported object or @null if there's no
264
+	 *                                         to be returned.
265
+	 * @param integer           $http_code     HTTP code to be used for HttpResponse sent.
266
+	 * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
267
+	 *                                         substitution or @null if none.
268
+	 * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
269
+	 *                                         options or pass @null to use value from your config (or defaults).
270
+	 *
271
+	 * @return HttpResponse
272
+	 *
273
+	 * @throws \InvalidArgumentException if http_code is @null
274
+	 */
275
+	public static function errorWithDataAndHttpCode(int $api_code, $data, int $http_code, array $placeholders = null,
276
+													int $json_opts = null): HttpResponse
277
+	{
278
+		return static::buildErrorResponse($data, $api_code, $http_code, $placeholders, $json_opts);
279
+	}
280
+
281
+	/**
282
+	 * @param integer    $api_code     Your API code to be returned with the response object.
283
+	 * @param integer    $http_code    HTTP code to be used for HttpResponse sent or @null
284
+	 *                                 for default DEFAULT_HTTP_CODE_ERROR.
285
+	 * @param array|null $placeholders Placeholders passed to Lang::get() for message placeholders
286
+	 *                                 substitution or @null if none.
287
+	 *
288
+	 * @return HttpResponse
289
+	 *
290
+	 * @throws \InvalidArgumentException if http_code is @null
291
+	 */
292
+	public static function errorWithHttpCode(int $api_code, int $http_code, array $placeholders = null): HttpResponse
293
+	{
294
+		return static::buildErrorResponse(null, $api_code, $http_code, $placeholders);
295
+	}
296
+
297
+	/**
298
+	 * @param integer           $api_code  Your API code to be returned with the response object.
299
+	 * @param string            $message   Custom message to be returned as part of error response
300
+	 * @param object|array|null $data      Array of primitives and supported objects to be returned in 'data' node
301
+	 *                                     of the JSON response, single supported object or @null if there's no
302
+	 *                                     to be returned.
303
+	 * @param integer|null      $http_code Optional HTTP status code to be used for HttpResponse sent
304
+	 *                                     or @null for DEFAULT_HTTP_CODE_ERROR
305
+	 * @param integer|null      $json_opts See http://php.net/manual/en/function.json-encode.php for supported
306
+	 *                                     options or pass @null to use value from your config (or defaults).
307
+	 *
308
+	 * @return HttpResponse
309
+	 */
310
+	public static function errorWithMessageAndData(int $api_code, string $message, $data,
311
+												   int $http_code = null, int $json_opts = null): HttpResponse
312
+	{
313
+		return static::buildErrorResponse($data, $api_code, $http_code, null,
314
+			$message, null, $json_opts);
315
+	}
316
+
317
+	/**
318
+	 * @param integer           $api_code   Your API code to be returned with the response object.
319
+	 * @param string            $message    custom message to be returned as part of error response
320
+	 * @param object|array|null $data       Array of primitives and supported objects to be returned in 'data' node
321
+	 *                                      of the JSON response, single supported object or @null if there's no
322
+	 *                                      to be returned.
323
+	 * @param integer|null      $http_code  HTTP code to be used for HttpResponse sent or @null
324
+	 *                                      for default DEFAULT_HTTP_CODE_ERROR.
325
+	 * @param integer|null      $json_opts  See http://php.net/manual/en/function.json-encode.php for supported
326
+	 *                                      options or pass @null to use value from your config (or defaults).
327
+	 * @param array|null        $debug_data optional debug data array to be added to returned JSON.
328
+	 *
329
+	 * @return HttpResponse
330
+	 */
331
+	public static function errorWithMessageAndDataAndDebug(int $api_code, string $message, $data,
332
+														   int $http_code = null, int $json_opts = null,
333
+														   array $debug_data = null): HttpResponse
334
+	{
335
+		return static::buildErrorResponse($data, $api_code, $http_code, null,
336
+			$message, null, $json_opts, $debug_data);
337
+	}
338
+
339
+	/**
340
+	 * @param integer      $api_code  Your API code to be returned with the response object.
341
+	 * @param string       $message   Custom message to be returned as part of error response
342
+	 * @param integer|null $http_code HTTP code to be used with final response sent or @null
343
+	 *                                for default DEFAULT_HTTP_CODE_ERROR.
344
+	 *
345
+	 * @return HttpResponse
346
+	 */
347
+	public static function errorWithMessage(int $api_code, string $message, int $http_code = null): HttpResponse
348
+	{
349
+		return static::buildErrorResponse(null, $api_code, $http_code, null, $message);
350
+	}
351
+
352
+	/**
353
+	 * Builds error Response object. Supports optional arguments passed to Lang::get() if associated error message
354
+	 * uses placeholders as well as return data payload
355
+	 *
356
+	 * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
357
+	 *                                         of the JSON response, single supported object or @null if there's no
358
+	 *                                         to be returned.
359
+	 * @param integer           $api_code      Your API code to be returned with the response object.
360
+	 * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
361
+	 *                                         for default DEFAULT_HTTP_CODE_ERROR.
362
+	 * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
363
+	 *                                         substitution or @null if none.
364
+	 * @param string|null       $message       custom message to be returned as part of error response
365
+	 * @param array|null        $headers       optional HTTP headers to be returned in error response
366
+	 * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
367
+	 *                                         options or pass @null to use value from your config (or defaults).
368
+	 * @param array|null        $debug_data    optional debug data array to be added to returned JSON.
369
+	 *
370
+	 * @return HttpResponse
371
+	 *
372
+	 * @throws \InvalidArgumentException Thrown if $code is not correct, outside the range, equals OK code etc.
373
+	 *
374
+	 * @noinspection MoreThanThreeArgumentsInspection
375
+	 */
376
+	protected static function buildErrorResponse($data, int $api_code, int $http_code = null,
377
+												 array $placeholders = null,
378
+												 string $message = null, array $headers = null,
379
+												 int $json_opts = null,
380
+												 array $debug_data = null): HttpResponse
381
+	{
382
+		$http_code = $http_code ?? static::DEFAULT_HTTP_CODE_ERROR;
383
+		$headers = $headers ?? [];
384
+
385
+		Validator::assertInt('api_code', $api_code);
386
+
387
+		$code_ok = BaseApiCodes::OK();
388
+		if ($api_code !== $code_ok) {
389
+			Validator::assertIntRange('api_code', $api_code, BaseApiCodes::getMinCode(), BaseApiCodes::getMaxCode());
390
+		}
391
+		if ($api_code === $code_ok) {
392
+			throw new \InvalidArgumentException(
393
+				"Error response cannot use api_code of value  {$code_ok} which is reserved for OK");
394
+		}
395
+
396
+		Validator::assertInt('http_code', $http_code);
397
+		Validator::assertIntRange('http_code', $http_code, static::ERROR_HTTP_CODE_MIN, static::ERROR_HTTP_CODE_MAX);
398
+
399
+		$msg_or_api_code = $message ?? $api_code;
400
+
401
+		return static::make(false, $api_code, $msg_or_api_code, $data, $http_code,
402
+			$placeholders, $headers, $json_opts, $debug_data);
403
+	}
404
+
405
+	/**
406
+	 * @param boolean           $success         @true if response reports successful operation, @false otherwise.
407
+	 * @param integer           $api_code        Your API code to be returned with the response object.
408
+	 * @param string|integer    $msg_or_api_code message string or valid API code to get message for
409
+	 * @param object|array|null $data            optional additional data to be included in response object
410
+	 * @param integer|null      $http_code       HTTP code for the HttpResponse or @null for either DEFAULT_HTTP_CODE_OK
411
+	 *                                           or DEFAULT_HTTP_CODE_ERROR depending on the $success.
412
+	 * @param array|null        $placeholders    Placeholders passed to Lang::get() for message placeholders
413
+	 *                                           substitution or @null if none.
414
+	 * @param array|null        $headers         Optional HTTP headers to be returned in the response.
415
+	 * @param integer|null      $json_opts       See http://php.net/manual/en/function.json-encode.php for supported
416
+	 *                                           options or pass @null to use value from your config (or defaults).
417
+	 * @param array|null        $debug_data      Optional debug data array to be added to returned JSON.
418
+	 *
419
+	 * @return HttpResponse
420
+	 *
421
+	 * @throws \InvalidArgumentException If $api_code is neither a string nor valid integer code.
422
+	 * @throws \InvalidArgumentException if $data is an object of class that is not configured in "classes" mapping.
423
+	 *
424
+	 * @noinspection MoreThanThreeArgumentsInspection
425
+	 */
426
+	protected static function make(bool $success, int $api_code, $msg_or_api_code, $data = null,
427
+								   int $http_code = null, array $placeholders = null, array $headers = null,
428
+								   int $json_opts = null, array $debug_data = null): HttpResponse
429
+	{
430
+		$headers = $headers ?? [];
431
+		$http_code = $http_code ?? ($success ? static::DEFAULT_HTTP_CODE_OK : static::DEFAULT_HTTP_CODE_ERROR);
432
+		$json_opts = $json_opts ?? Config::get(self::CONF_KEY_ENCODING_OPTIONS, static::DEFAULT_ENCODING_OPTIONS);
433
+
434
+		Validator::assertInt('encoding_options', $json_opts);
435
+
436
+		Validator::assertInt('api_code', $api_code);
437
+		if (!BaseApiCodes::isCodeValid($api_code)) {
438
+			$min = BaseApiCodes::getMinCode();
439
+			$max = BaseApiCodes::getMaxCode();
440
+			throw new \InvalidArgumentException("API code value ({$api_code}) is out of allowed range {$min}-{$max}");
441
+		}
442
+
443
+		return Response::json(
444
+			static::buildResponse($success, $api_code, $msg_or_api_code, $placeholders, $data, $debug_data),
445
+			$http_code, $headers, $json_opts);
446
+	}
447
+
448
+	/**
449
+	 * If $msg_or_api_code is integer value, returns human readable message associated with that code (with
450
+	 * fallback to built-in default string if no api code mapping is set. If $msg_or_api_code is a string,
451
+	 * returns it unaltered.
452
+	 *
453
+	 * @param boolean    $success      @true if response reports successful operation, @false otherwise.
454
+	 * @param integer    $api_code     Your API code to be returned with the response object.
455
+	 * @param array|null $placeholders Placeholders passed to Lang::get() for message placeholders
456
+	 *                                 substitution or @null if none.
457
+	 *
458
+	 * @return string
459
+	 */
460
+	protected static function getMessageForApiCode(bool $success, int $api_code, array $placeholders = null): string
461
+	{
462
+		// We got integer value here not a message string, so we need to check if we have the mapping for
463
+		// this string already configured.
464
+		$key = BaseApiCodes::getCodeMessageKey($api_code);
465
+		if ($key === null) {
466
+			// nope, let's get the default one instead, based of
467
+			$fallback_code = $success ? BaseApiCodes::OK() : BaseApiCodes::NO_ERROR_MESSAGE();
468
+			$key = BaseApiCodes::getCodeMessageKey($fallback_code);
469
+		}
470
+
471
+		$placeholders = $placeholders ?? [];
472
+		if (!array_key_exists('api_code', $placeholders)) {
473
+			$placeholders['api_code'] = $api_code;
474
+		}
475
+
476
+		return \Lang::get($key, $placeholders);
477
+	}
478
+
479
+	/**
480
+	 * Creates standardised API response array. This is final method called in the whole pipeline before we
481
+	 * return final JSON back to client. If you want to manipulate your response, this is the place to do that.
482
+	 * If you set APP_DEBUG to true, 'code_hex' field will be additionally added to reported JSON for easier
483
+	 * manual debugging.
484
+	 *
485
+	 * @param boolean           $success         @true if response reports successful operation, @false otherwise.
486
+	 * @param integer           $api_code        Your API code to be returned with the response object.
487
+	 * @param string|integer    $msg_or_api_code Message string or valid API code to get message for.
488
+	 * @param array|null        $placeholders    Placeholders passed to Lang::get() for message placeholders
489
+	 *                                           substitution or @null if none.
490
+	 * @param object|array|null $data            API response data if any
491
+	 * @param array|null        $debug_data      optional debug data array to be added to returned JSON.
492
+	 *
493
+	 * @return array response ready to be encoded as json and sent back to client
494
+	 *
495
+	 * @throws \RuntimeException in case of missing or invalid "classes" mapping configuration
496
+	 */
497
+	protected static function buildResponse(bool $success, int $api_code,
498
+											$msg_or_api_code, array $placeholders = null,
499
+											$data = null, array $debug_data = null): array
500
+	{
501
+		// ensure $data is either @null, array or object of class with configured mapping.
502
+		$converter = new Converter();
503
+
504
+		$data = $converter->convert($data);
505
+		if ($data !== null && !is_object($data)) {
506
+			// ensure we get object in final JSON structure in data node
507
+			$data = (object)$data;
508
+		}
509
+
510
+		// get human readable message for API code or use message string (if given instead of API code)
511
+		if (is_int($msg_or_api_code)) {
512
+			$message = self::getMessageForApiCode($success, $msg_or_api_code, $placeholders);
513
+		} else {
514
+			Validator::assertString('message', $msg_or_api_code);
515
+			$message = $msg_or_api_code;
516
+		}
517
+
518
+		/** @noinspection PhpUndefinedClassInspection */
519
+		$response = [
520
+			static::KEY_SUCCESS => $success,
521
+			static::KEY_CODE    => $api_code,
522
+			static::KEY_LOCALE  => \App::getLocale(),
523
+			static::KEY_MESSAGE => $message,
524
+			static::KEY_DATA    => $data,
525
+		];
526
+
527
+		if ($debug_data !== null) {
528
+			$debug_key = Config::get(static::CONF_KEY_DEBUG_DEBUG_KEY, self::KEY_DEBUG);
529
+			$response[ $debug_key ] = $debug_data;
530
+		}
531
+
532
+		return $response;
533
+	}
534 534
 
535 535
 }
Please login to merge, or discard this patch.
src/ApiCodesHelpers.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -112,7 +112,7 @@
 block discarded – undo
112 112
 
113 113
         $map = static::getMap();
114 114
 
115
-        return $map[ $api_code ] ?? null;
115
+        return $map[$api_code] ?? null;
116 116
     }
117 117
 
118 118
     /**
Please login to merge, or discard this patch.
Indentation   +123 added lines, -123 removed lines patch added patch discarded remove patch
@@ -21,128 +21,128 @@
 block discarded – undo
21 21
  */
22 22
 trait ApiCodesHelpers
23 23
 {
24
-    /**
25
-     * Returns lowest allowed error code for this module
26
-     *
27
-     * @return integer
28
-     *
29
-     * @throws \RuntimeException Throws exception if no min_code set up
30
-     */
31
-    public static function getMinCode(): int
32
-    {
33
-        $key = ResponseBuilder::CONF_KEY_MIN_CODE;
34
-        $min_code = Config::get($key, null);
35
-
36
-        if ($min_code === null) {
37
-            throw new \RuntimeException(sprintf('CONFIG: Missing "%s" key', $key));
38
-        }
39
-
40
-        return $min_code;
41
-    }
42
-
43
-    /**
44
-     * Returns highest allowed error code for this module
45
-     *
46
-     * @return integer
47
-     *
48
-     * @throws \RuntimeException Throws exception if no max_code set up
49
-     */
50
-    public static function getMaxCode(): int
51
-    {
52
-        $key = ResponseBuilder::CONF_KEY_MAX_CODE;
53
-        $max_code = Config::get($key, null);
54
-
55
-        if ($max_code === null) {
56
-            throw new \RuntimeException(sprintf('CONFIG: Missing "%s" key', $key));
57
-        }
58
-
59
-        return $max_code;
60
-    }
61
-
62
-    /**
63
-     * Returns array of error code constants defined in this class. Used mainly for debugging/tests
64
-     *
65
-     * @return array
66
-     * @throws \ReflectionException
67
-     */
68
-    public static function getApiCodeConstants(): array
69
-    {
70
-        /** @noinspection PhpUnhandledExceptionInspection */
71
-        return (new \ReflectionClass(static::class))->getConstants();
72
-    }
73
-
74
-    /**
75
-     * Returns complete error code to locale string mapping array
76
-     *
77
-     * @return array
78
-     *
79
-     * @throws \RuntimeException Thrown when builder map is not configured.
80
-     */
81
-    public static function getMap(): array
82
-    {
83
-        $user_map = Config::get(ResponseBuilder::CONF_KEY_MAP, null);
84
-        if ($user_map === null) {
85
-            throw new \RuntimeException(sprintf('CONFIG: Missing "%s" key', ResponseBuilder::CONF_KEY_MAP));
86
-        }
87
-        if (!is_array($user_map)) {
88
-            throw new \RuntimeException(sprintf('CONFIG: "%s" must be an array', ResponseBuilder::CONF_KEY_MAP));
89
-        }
90
-        return Util::mergeConfig(BaseApiCodes::getBaseMap(), $user_map);
91
-    }
92
-
93
-    /**
94
-     * Returns locale mappings key for given api code or @null if there's no mapping
95
-     *
96
-     * @param integer $api_code Api code to look for mapped message for.
97
-     *
98
-     * @return string|null
99
-     *
100
-     * @throws \InvalidArgumentException If $code is not in allowed range.
101
-     */
102
-    public static function getCodeMessageKey(int $api_code): ?string
103
-    {
104
-        if (!static::isCodeValid($api_code)) {
105
-            $min = static::getMinCode();
106
-            $max = static::getMaxCode();
107
-            throw new \InvalidArgumentException("API code value ({$api_code}) is out of allowed range {$min}-{$max}");
108
-        }
109
-
110
-        $map = static::getMap();
111
-
112
-        return $map[ $api_code ] ?? null;
113
-    }
114
-
115
-    /**
116
-     * Checks if given API $code can be used in current configuration.
117
-     *
118
-     * @param int $code API code to validate
119
-     *
120
-     * @return bool
121
-     */
122
-    public static function isCodeValid(int $code): bool
123
-    {
124
-        return ($code === 0) || (($code >= static::getMinCode()) && ($code <= static::getMaxCode()));
125
-    }
126
-
127
-    /**
128
-     * Returns final API code for internal code, remapped to configured code range
129
-     *
130
-     * @param int $internal_code
131
-     *
132
-     * @return int
133
-     *
134
-     * @throws \InvalidArgumentException
135
-     */
136
-    protected static function getCodeForInternalOffset(int $internal_code): int
137
-    {
138
-        $min = static::RESERVED_MIN_API_CODE_OFFSET;
139
-        $max = static::RESERVED_MAX_API_CODE_OFFSET;
140
-        if (($internal_code < $min) || ($internal_code > $max)) {
141
-            throw new \InvalidArgumentException(
142
-                "Invalid internal code ({$internal_code}). Must be between {$min}-{$max} inclusive.");
143
-        }
144
-
145
-        return ($internal_code === 0) ? 0 : $internal_code + static::getMinCode();
146
-    }
24
+	/**
25
+	 * Returns lowest allowed error code for this module
26
+	 *
27
+	 * @return integer
28
+	 *
29
+	 * @throws \RuntimeException Throws exception if no min_code set up
30
+	 */
31
+	public static function getMinCode(): int
32
+	{
33
+		$key = ResponseBuilder::CONF_KEY_MIN_CODE;
34
+		$min_code = Config::get($key, null);
35
+
36
+		if ($min_code === null) {
37
+			throw new \RuntimeException(sprintf('CONFIG: Missing "%s" key', $key));
38
+		}
39
+
40
+		return $min_code;
41
+	}
42
+
43
+	/**
44
+	 * Returns highest allowed error code for this module
45
+	 *
46
+	 * @return integer
47
+	 *
48
+	 * @throws \RuntimeException Throws exception if no max_code set up
49
+	 */
50
+	public static function getMaxCode(): int
51
+	{
52
+		$key = ResponseBuilder::CONF_KEY_MAX_CODE;
53
+		$max_code = Config::get($key, null);
54
+
55
+		if ($max_code === null) {
56
+			throw new \RuntimeException(sprintf('CONFIG: Missing "%s" key', $key));
57
+		}
58
+
59
+		return $max_code;
60
+	}
61
+
62
+	/**
63
+	 * Returns array of error code constants defined in this class. Used mainly for debugging/tests
64
+	 *
65
+	 * @return array
66
+	 * @throws \ReflectionException
67
+	 */
68
+	public static function getApiCodeConstants(): array
69
+	{
70
+		/** @noinspection PhpUnhandledExceptionInspection */
71
+		return (new \ReflectionClass(static::class))->getConstants();
72
+	}
73
+
74
+	/**
75
+	 * Returns complete error code to locale string mapping array
76
+	 *
77
+	 * @return array
78
+	 *
79
+	 * @throws \RuntimeException Thrown when builder map is not configured.
80
+	 */
81
+	public static function getMap(): array
82
+	{
83
+		$user_map = Config::get(ResponseBuilder::CONF_KEY_MAP, null);
84
+		if ($user_map === null) {
85
+			throw new \RuntimeException(sprintf('CONFIG: Missing "%s" key', ResponseBuilder::CONF_KEY_MAP));
86
+		}
87
+		if (!is_array($user_map)) {
88
+			throw new \RuntimeException(sprintf('CONFIG: "%s" must be an array', ResponseBuilder::CONF_KEY_MAP));
89
+		}
90
+		return Util::mergeConfig(BaseApiCodes::getBaseMap(), $user_map);
91
+	}
92
+
93
+	/**
94
+	 * Returns locale mappings key for given api code or @null if there's no mapping
95
+	 *
96
+	 * @param integer $api_code Api code to look for mapped message for.
97
+	 *
98
+	 * @return string|null
99
+	 *
100
+	 * @throws \InvalidArgumentException If $code is not in allowed range.
101
+	 */
102
+	public static function getCodeMessageKey(int $api_code): ?string
103
+	{
104
+		if (!static::isCodeValid($api_code)) {
105
+			$min = static::getMinCode();
106
+			$max = static::getMaxCode();
107
+			throw new \InvalidArgumentException("API code value ({$api_code}) is out of allowed range {$min}-{$max}");
108
+		}
109
+
110
+		$map = static::getMap();
111
+
112
+		return $map[ $api_code ] ?? null;
113
+	}
114
+
115
+	/**
116
+	 * Checks if given API $code can be used in current configuration.
117
+	 *
118
+	 * @param int $code API code to validate
119
+	 *
120
+	 * @return bool
121
+	 */
122
+	public static function isCodeValid(int $code): bool
123
+	{
124
+		return ($code === 0) || (($code >= static::getMinCode()) && ($code <= static::getMaxCode()));
125
+	}
126
+
127
+	/**
128
+	 * Returns final API code for internal code, remapped to configured code range
129
+	 *
130
+	 * @param int $internal_code
131
+	 *
132
+	 * @return int
133
+	 *
134
+	 * @throws \InvalidArgumentException
135
+	 */
136
+	protected static function getCodeForInternalOffset(int $internal_code): int
137
+	{
138
+		$min = static::RESERVED_MIN_API_CODE_OFFSET;
139
+		$max = static::RESERVED_MAX_API_CODE_OFFSET;
140
+		if (($internal_code < $min) || ($internal_code > $max)) {
141
+			throw new \InvalidArgumentException(
142
+				"Invalid internal code ({$internal_code}). Must be between {$min}-{$max} inclusive.");
143
+		}
144
+
145
+		return ($internal_code === 0) ? 0 : $internal_code + static::getMinCode();
146
+	}
147 147
 
148 148
 }
Please login to merge, or discard this patch.
src/Validator.php 1 patch
Indentation   +76 added lines, -76 removed lines patch added patch discarded remove patch
@@ -15,88 +15,88 @@
 block discarded – undo
15 15
  */
16 16
 class Validator
17 17
 {
18
-    /** @var string */
19
-    public const TYPE_STRING = 'string';
18
+	/** @var string */
19
+	public const TYPE_STRING = 'string';
20 20
 
21
-    /** @var string */
22
-    public const TYPE_INTEGER = 'integer';
21
+	/** @var string */
22
+	public const TYPE_INTEGER = 'integer';
23 23
 
24
-    /** @var string */
25
-    public const TYPE_BOOL = 'boolean';
24
+	/** @var string */
25
+	public const TYPE_BOOL = 'boolean';
26 26
 
27
-    /**
28
-     * Checks if given $val is of type integer
29
-     *
30
-     * @param string $key Name of the key to be used if exception is thrown.
31
-     * @param mixed  $var Variable to be asserted.
32
-     *
33
-     * @return void
34
-     *
35
-     * @throws \InvalidArgumentException
36
-     */
37
-    public static function assertInt(string $key, $var): void
38
-    {
39
-        self::assertType($key, $var, [self::TYPE_INTEGER]);
40
-    }
27
+	/**
28
+	 * Checks if given $val is of type integer
29
+	 *
30
+	 * @param string $key Name of the key to be used if exception is thrown.
31
+	 * @param mixed  $var Variable to be asserted.
32
+	 *
33
+	 * @return void
34
+	 *
35
+	 * @throws \InvalidArgumentException
36
+	 */
37
+	public static function assertInt(string $key, $var): void
38
+	{
39
+		self::assertType($key, $var, [self::TYPE_INTEGER]);
40
+	}
41 41
 
42
-    /**
43
-     * Checks if given $val is of type string
44
-     *
45
-     * @param string $name Label or name of the variable to be used in exception message (if thrown).
46
-     * @param mixed  $var  Variable to be asserted.
47
-     *
48
-     * @return void
49
-     *
50
-     * @throws \InvalidArgumentException
51
-     */
52
-    public static function assertString(string $name, $var): void
53
-    {
54
-        self::assertType($name, $var, [self::TYPE_STRING]);
55
-    }
42
+	/**
43
+	 * Checks if given $val is of type string
44
+	 *
45
+	 * @param string $name Label or name of the variable to be used in exception message (if thrown).
46
+	 * @param mixed  $var  Variable to be asserted.
47
+	 *
48
+	 * @return void
49
+	 *
50
+	 * @throws \InvalidArgumentException
51
+	 */
52
+	public static function assertString(string $name, $var): void
53
+	{
54
+		self::assertType($name, $var, [self::TYPE_STRING]);
55
+	}
56 56
 
57
-    /**
58
-     * @param string $name Label or name of the variable to be used in exception message (if thrown).
59
-     * @param mixed  $var  Variable to be asserted.
60
-     * @param int    $min  Min allowed value (inclusive)
61
-     * @param int    $max  Max allowed value (inclusive)
62
-     *
63
-     * @return void
64
-     *
65
-     * @throws \InvalidArgumentException
66
-     * @throws \RuntimeException
67
-     */
68
-    public static function assertIntRange(string $name, $var, int $min, int $max): void
69
-    {
70
-        self::assertInt($name, $var);
57
+	/**
58
+	 * @param string $name Label or name of the variable to be used in exception message (if thrown).
59
+	 * @param mixed  $var  Variable to be asserted.
60
+	 * @param int    $min  Min allowed value (inclusive)
61
+	 * @param int    $max  Max allowed value (inclusive)
62
+	 *
63
+	 * @return void
64
+	 *
65
+	 * @throws \InvalidArgumentException
66
+	 * @throws \RuntimeException
67
+	 */
68
+	public static function assertIntRange(string $name, $var, int $min, int $max): void
69
+	{
70
+		self::assertInt($name, $var);
71 71
 
72
-        if ($min > $max) {
73
-            throw new \RuntimeException(
74
-                sprintf('%s: Invalid range for "%s". Ensure bound values are not swapped.', __FUNCTION__, $name));
75
-        }
72
+		if ($min > $max) {
73
+			throw new \RuntimeException(
74
+				sprintf('%s: Invalid range for "%s". Ensure bound values are not swapped.', __FUNCTION__, $name));
75
+		}
76 76
 
77
-        if (($min > $var) || ($var > $max)) {
78
-            throw new \InvalidArgumentException(
79
-                sprintf('Invalid value of "%s" (%d). Must be between %d-%d inclusive.', $name, $var, $min, $max));
80
-        }
81
-    }
77
+		if (($min > $var) || ($var > $max)) {
78
+			throw new \InvalidArgumentException(
79
+				sprintf('Invalid value of "%s" (%d). Must be between %d-%d inclusive.', $name, $var, $min, $max));
80
+		}
81
+	}
82 82
 
83
-    /**
84
-     * Checks if $item (of name $key) is of type that is include in $allowed_types.
85
-     *
86
-     * @param string $name          Label or name of the variable to be used in exception message (if thrown).
87
-     * @param mixed  $var           Variable to be asserted.
88
-     * @param array  $allowed_types Array of allowed types for $var, i.e. [Validator::TYPE_INTEGER]
89
-     *
90
-     * @return void
91
-     *
92
-     * @throws \InvalidArgumentException
93
-     */
94
-    public static function assertType(string $name, $var, array $allowed_types): void
95
-    {
96
-        $type = gettype($var);
97
-        if (!in_array($type, $allowed_types)) {
98
-            $msg = sprintf('"%s" must be one of allowed types: %s (%s given)', $name, implode(', ', $allowed_types), gettype($var));
99
-            throw new \InvalidArgumentException($msg);
100
-        }
101
-    }
83
+	/**
84
+	 * Checks if $item (of name $key) is of type that is include in $allowed_types.
85
+	 *
86
+	 * @param string $name          Label or name of the variable to be used in exception message (if thrown).
87
+	 * @param mixed  $var           Variable to be asserted.
88
+	 * @param array  $allowed_types Array of allowed types for $var, i.e. [Validator::TYPE_INTEGER]
89
+	 *
90
+	 * @return void
91
+	 *
92
+	 * @throws \InvalidArgumentException
93
+	 */
94
+	public static function assertType(string $name, $var, array $allowed_types): void
95
+	{
96
+		$type = gettype($var);
97
+		if (!in_array($type, $allowed_types)) {
98
+			$msg = sprintf('"%s" must be one of allowed types: %s (%s given)', $name, implode(', ', $allowed_types), gettype($var));
99
+			throw new \InvalidArgumentException($msg);
100
+		}
101
+	}
102 102
 }
Please login to merge, or discard this patch.
src/Util.php 2 patches
Indentation   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -15,43 +15,43 @@
 block discarded – undo
15 15
  */
16 16
 final class Util
17 17
 {
18
-    /**
19
-     * Merges the configs together and takes multi-dimensional arrays into account.
20
-     * Support for multi-dimensional config array. Built-in config merge only supports flat arrays.
21
-     * Throws \RuntimeException if arrays stucture causes type conflics (i.e. you want to merge
22
-     * array with int).
23
-     *
24
-     * @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.
27
-     *
28
-     * @return array
29
-     *
30
-     * @throws \RuntimeException
31
-     */
32
-    public static function mergeConfig(array $original, array $merging): array
33
-    {
34
-        $array = $original;
35
-        foreach ($merging as $m_key => $m_val) {
36
-            if (array_key_exists($m_key, $original)) {
37
-                $orig_type = gettype($original[ $m_key ]);
38
-                $m_type = gettype($m_val);
39
-                if ($orig_type !== $m_type) {
40
-                    throw new \RuntimeException(
41
-                        "Incompatible types. Cannot merge {$m_type} into {$orig_type} (key '{$m_key}').");
42
-                }
18
+	/**
19
+	 * Merges the configs together and takes multi-dimensional arrays into account.
20
+	 * Support for multi-dimensional config array. Built-in config merge only supports flat arrays.
21
+	 * Throws \RuntimeException if arrays stucture causes type conflics (i.e. you want to merge
22
+	 * array with int).
23
+	 *
24
+	 * @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.
27
+	 *
28
+	 * @return array
29
+	 *
30
+	 * @throws \RuntimeException
31
+	 */
32
+	public static function mergeConfig(array $original, array $merging): array
33
+	{
34
+		$array = $original;
35
+		foreach ($merging as $m_key => $m_val) {
36
+			if (array_key_exists($m_key, $original)) {
37
+				$orig_type = gettype($original[ $m_key ]);
38
+				$m_type = gettype($m_val);
39
+				if ($orig_type !== $m_type) {
40
+					throw new \RuntimeException(
41
+						"Incompatible types. Cannot merge {$m_type} into {$orig_type} (key '{$m_key}').");
42
+				}
43 43
 
44
-                if (is_array($merging[ $m_key ])) {
45
-                    $array[ $m_key ] = static::mergeConfig($original[ $m_key ], $m_val);
46
-                } else {
47
-                    $array[ $m_key ] = $m_val;
48
-                }
49
-            } else {
50
-                $array[ $m_key ] = $m_val;
51
-            }
52
-        }
44
+				if (is_array($merging[ $m_key ])) {
45
+					$array[ $m_key ] = static::mergeConfig($original[ $m_key ], $m_val);
46
+				} else {
47
+					$array[ $m_key ] = $m_val;
48
+				}
49
+			} else {
50
+				$array[ $m_key ] = $m_val;
51
+			}
52
+		}
53 53
 
54
-        return $array;
55
-    }
54
+		return $array;
55
+	}
56 56
 
57 57
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -34,20 +34,20 @@
 block discarded – undo
34 34
         $array = $original;
35 35
         foreach ($merging as $m_key => $m_val) {
36 36
             if (array_key_exists($m_key, $original)) {
37
-                $orig_type = gettype($original[ $m_key ]);
37
+                $orig_type = gettype($original[$m_key]);
38 38
                 $m_type = gettype($m_val);
39 39
                 if ($orig_type !== $m_type) {
40 40
                     throw new \RuntimeException(
41 41
                         "Incompatible types. Cannot merge {$m_type} into {$orig_type} (key '{$m_key}').");
42 42
                 }
43 43
 
44
-                if (is_array($merging[ $m_key ])) {
45
-                    $array[ $m_key ] = static::mergeConfig($original[ $m_key ], $m_val);
44
+                if (is_array($merging[$m_key])) {
45
+                    $array[$m_key] = static::mergeConfig($original[$m_key], $m_val);
46 46
                 } else {
47
-                    $array[ $m_key ] = $m_val;
47
+                    $array[$m_key] = $m_val;
48 48
                 }
49 49
             } else {
50
-                $array[ $m_key ] = $m_val;
50
+                $array[$m_key] = $m_val;
51 51
             }
52 52
         }
53 53
 
Please login to merge, or discard this patch.
src/ResponseBuilderServiceProvider.php 1 patch
Indentation   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -25,45 +25,45 @@
 block discarded – undo
25 25
 
26 26
 class ResponseBuilderServiceProvider extends ServiceProvider
27 27
 {
28
-    /**
29
-     * Register bindings in the container.
30
-     *
31
-     * @return void
32
-     */
33
-    public function register()
34
-    {
35
-        $this->mergeConfigFrom(
36
-            __DIR__ . '/../config/response_builder.php', 'response_builder'
37
-        );
38
-    }
28
+	/**
29
+	 * Register bindings in the container.
30
+	 *
31
+	 * @return void
32
+	 */
33
+	public function register()
34
+	{
35
+		$this->mergeConfigFrom(
36
+			__DIR__ . '/../config/response_builder.php', 'response_builder'
37
+		);
38
+	}
39 39
 
40
-    /**
41
-     * Sets up package resources
42
-     *
43
-     * @return void
44
-     */
45
-    public function boot()
46
-    {
47
-        $this->loadTranslationsFrom(__DIR__ . '/lang', 'response-builder');
40
+	/**
41
+	 * Sets up package resources
42
+	 *
43
+	 * @return void
44
+	 */
45
+	public function boot()
46
+	{
47
+		$this->loadTranslationsFrom(__DIR__ . '/lang', 'response-builder');
48 48
 
49
-        $source = __DIR__ . '/../config/response_builder.php';
50
-        $this->publishes([
51
-            $source => config_path('response_builder.php'),
52
-        ]);
53
-    }
49
+		$source = __DIR__ . '/../config/response_builder.php';
50
+		$this->publishes([
51
+			$source => config_path('response_builder.php'),
52
+		]);
53
+	}
54 54
 
55
-    /**
56
-     * Merge the given configuration with the existing configuration.
57
-     *
58
-     * @param string $path
59
-     * @param string $key
60
-     *
61
-     * @return void
62
-     */
63
-    protected function mergeConfigFrom($path, $key)
64
-    {
65
-        $config = $this->app['config']->get($key, []);
66
-        $this->app['config']->set($key, Util::mergeConfig(require $path, $config));
67
-    }
55
+	/**
56
+	 * Merge the given configuration with the existing configuration.
57
+	 *
58
+	 * @param string $path
59
+	 * @param string $key
60
+	 *
61
+	 * @return void
62
+	 */
63
+	protected function mergeConfigFrom($path, $key)
64
+	{
65
+		$config = $this->app['config']->get($key, []);
66
+		$this->app['config']->set($key, Util::mergeConfig(require $path, $config));
67
+	}
68 68
 
69 69
 }
Please login to merge, or discard this patch.
src/ExceptionHandlerHelper.php 1 patch
Indentation   +159 added lines, -159 removed lines patch added patch discarded remove patch
@@ -27,165 +27,165 @@
 block discarded – undo
27 27
  */
28 28
 class ExceptionHandlerHelper
29 29
 {
30
-    /**
31
-     * Exception types
32
-     */
33
-    public const TYPE_HTTP_NOT_FOUND_KEY           = 'http_not_found';
34
-    public const TYPE_HTTP_SERVICE_UNAVAILABLE_KEY = 'http_service_unavailable';
35
-    public const TYPE_HTTP_UNAUTHORIZED_KEY        = 'authentication_exception';
36
-    public const TYPE_HTTP_EXCEPTION_KEY           = 'http_exception';
37
-    public const TYPE_VALIDATION_EXCEPTION_KEY     = 'validation_exception';
38
-    public const TYPE_UNCAUGHT_EXCEPTION_KEY       = 'uncaught_exception';
39
-    public const TYPE_AUTHENTICATION_EXCEPTION_KEY = 'authentication_exception';
40
-
41
-    /**
42
-     * Render an exception into valid API response.
43
-     *
44
-     * @param \Illuminate\Http\Request $request   Request object
45
-     * @param \Exception               $exception Exception
46
-     *
47
-     * @return HttpResponse
48
-     */
49
-    public static function render(/** @scrutinizer ignore-unused */ $request, Exception $exception): HttpResponse
50
-    {
51
-        $result = null;
52
-
53
-        if ($exception instanceof HttpException) {
54
-            switch ($exception->getStatusCode()) {
55
-                case HttpResponse::HTTP_NOT_FOUND:
56
-                    $result = static::error($exception, static::TYPE_HTTP_NOT_FOUND_KEY,
57
-                        BaseApiCodes::EX_HTTP_NOT_FOUND(), HttpResponse::HTTP_NOT_FOUND);
58
-                    break;
59
-
60
-                case HttpResponse::HTTP_SERVICE_UNAVAILABLE:
61
-                    $result = static::error($exception, static::TYPE_HTTP_SERVICE_UNAVAILABLE_KEY,
62
-                        BaseApiCodes::EX_HTTP_SERVICE_UNAVAILABLE(), HttpResponse::HTTP_SERVICE_UNAVAILABLE);
63
-                    break;
64
-
65
-                case HttpResponse::HTTP_UNAUTHORIZED:
66
-                    $result = static::error($exception, static::TYPE_HTTP_UNAUTHORIZED_KEY,
67
-                        BaseApiCodes::EX_AUTHENTICATION_EXCEPTION(), HttpResponse::HTTP_UNAUTHORIZED);
68
-                    break;
69
-
70
-                default:
71
-                    $result = static::error($exception, static::TYPE_HTTP_EXCEPTION_KEY,
72
-                        BaseApiCodes::EX_HTTP_EXCEPTION(), HttpResponse::HTTP_BAD_REQUEST);
73
-                    break;
74
-            }
75
-        } elseif ($exception instanceof ValidationException) {
76
-            $result = static::error($exception, static::TYPE_VALIDATION_EXCEPTION_KEY,
77
-                BaseApiCodes::EX_VALIDATION_EXCEPTION(), HttpResponse::HTTP_BAD_REQUEST);
78
-        }
79
-
80
-        if ($result === null) {
81
-            $result = static::error($exception, static::TYPE_UNCAUGHT_EXCEPTION_KEY,
82
-                BaseApiCodes::EX_UNCAUGHT_EXCEPTION(), HttpResponse::HTTP_INTERNAL_SERVER_ERROR);
83
-        }
84
-
85
-        return $result;
86
-    }
87
-
88
-    /**
89
-     * Convert an authentication exception into an unauthenticated response.
90
-     *
91
-     * @param \Illuminate\Http\Request                 $request
92
-     * @param \Illuminate\Auth\AuthenticationException $exception
93
-     *
94
-     * @return HttpResponse
95
-     */
96
-    protected function unauthenticated(/** @scrutinizer ignore-unused */ $request,
97
-                                                                         AuthenticationException $exception): HttpResponse
98
-    {
99
-        return static::error($exception, 'authentication_exception', BaseApiCodes::EX_AUTHENTICATION_EXCEPTION());
100
-    }
101
-
102
-    /**
103
-     * Process singe error and produce valid API response
104
-     *
105
-     * @param Exception $exception            Exception to be processed
106
-     * @param string    $exception_config_key Category of the exception
107
-     * @param integer   $fallback_api_code    API code to return
108
-     * @param integer   $fallback_http_code   HTTP code to return
109
-     *
110
-     * @return HttpResponse
111
-     */
112
-    protected static function error(Exception $exception, $exception_config_key, $fallback_api_code,
113
-                                    $fallback_http_code = ResponseBuilder::DEFAULT_HTTP_CODE_ERROR): HttpResponse
114
-    {
115
-        // common prefix for config key
116
-        $base_key = sprintf('%s.exception', ResponseBuilder::CONF_EXCEPTION_HANDLER_KEY);
117
-
118
-        // get API and HTTP codes from exception handler config or use fallback values if no such
119
-        // config fields are set.
120
-        $api_code = Config::get("{$base_key}.{$exception_config_key}.code", $fallback_api_code);
121
-        $http_code = Config::get("{$base_key}.{$exception_config_key}.http_code", $fallback_http_code);
122
-
123
-        // check if we now have valid HTTP error code for this case or need to make one up.
124
-        if ($http_code < ResponseBuilder::ERROR_HTTP_CODE_MIN) {
125
-            // no code, let's try to get the exception status
126
-            $http_code = ($exception instanceof \Symfony\Component\HttpKernel\Exception\HttpException)
127
-                ? $exception->getStatusCode()
128
-                : $exception->getCode();
129
-        }
130
-
131
-        // can it be considered valid HTTP error code?
132
-        if ($http_code < ResponseBuilder::ERROR_HTTP_CODE_MIN) {
133
-            $http_code = $fallback_http_code;
134
-        }
135
-
136
-        // let's figure out what event we are handling now
137
-        $known_codes = [
138
-            self::TYPE_HTTP_NOT_FOUND_KEY           => BaseApiCodes::EX_HTTP_NOT_FOUND(),
139
-            self::TYPE_HTTP_SERVICE_UNAVAILABLE_KEY => BaseApiCodes::EX_HTTP_SERVICE_UNAVAILABLE(),
140
-            self::TYPE_UNCAUGHT_EXCEPTION_KEY       => BaseApiCodes::EX_UNCAUGHT_EXCEPTION(),
141
-            self::TYPE_AUTHENTICATION_EXCEPTION_KEY => BaseApiCodes::EX_AUTHENTICATION_EXCEPTION(),
142
-            self::TYPE_VALIDATION_EXCEPTION_KEY     => BaseApiCodes::EX_VALIDATION_EXCEPTION(),
143
-            self::TYPE_HTTP_EXCEPTION_KEY           => BaseApiCodes::EX_HTTP_EXCEPTION(),
144
-        ];
145
-        $base_api_code = BaseApiCodes::NO_ERROR_MESSAGE();
146
-        foreach ($known_codes as $item_config_key => $item_api_code) {
147
-            if ($api_code === Config::get("{$base_key}.{$item_config_key}.code", $item_api_code)) {
148
-                $base_api_code = $api_code;
149
-                break;
150
-            }
151
-        }
152
-
153
-        /** @var array|null $data Optional payload to return */
154
-        $data = null;
155
-        if ($api_code === Config::get("{$base_key}.validation_exception.code", BaseApiCodes::EX_VALIDATION_EXCEPTION())) {
156
-            /** @var ValidationException $exception */
157
-            $data = [ResponseBuilder::KEY_MESSAGES => $exception->validator->errors()->messages()];
158
-        }
159
-
160
-        $key = BaseApiCodes::getCodeMessageKey($api_code) ?? BaseApiCodes::getCodeMessageKey($base_api_code);
161
-
162
-        // let's build error error_message
163
-        $error_message = $exception->getMessage();
164
-
165
-        // if we do not have any error_message in the hand yet, we need to fall back to built-in string configured
166
-        // for this particular exception.
167
-        if ($error_message === '') {
168
-            $error_message = Lang::get($key, [
169
-                'api_code' => $api_code,
30
+	/**
31
+	 * Exception types
32
+	 */
33
+	public const TYPE_HTTP_NOT_FOUND_KEY           = 'http_not_found';
34
+	public const TYPE_HTTP_SERVICE_UNAVAILABLE_KEY = 'http_service_unavailable';
35
+	public const TYPE_HTTP_UNAUTHORIZED_KEY        = 'authentication_exception';
36
+	public const TYPE_HTTP_EXCEPTION_KEY           = 'http_exception';
37
+	public const TYPE_VALIDATION_EXCEPTION_KEY     = 'validation_exception';
38
+	public const TYPE_UNCAUGHT_EXCEPTION_KEY       = 'uncaught_exception';
39
+	public const TYPE_AUTHENTICATION_EXCEPTION_KEY = 'authentication_exception';
40
+
41
+	/**
42
+	 * Render an exception into valid API response.
43
+	 *
44
+	 * @param \Illuminate\Http\Request $request   Request object
45
+	 * @param \Exception               $exception Exception
46
+	 *
47
+	 * @return HttpResponse
48
+	 */
49
+	public static function render(/** @scrutinizer ignore-unused */ $request, Exception $exception): HttpResponse
50
+	{
51
+		$result = null;
52
+
53
+		if ($exception instanceof HttpException) {
54
+			switch ($exception->getStatusCode()) {
55
+				case HttpResponse::HTTP_NOT_FOUND:
56
+					$result = static::error($exception, static::TYPE_HTTP_NOT_FOUND_KEY,
57
+						BaseApiCodes::EX_HTTP_NOT_FOUND(), HttpResponse::HTTP_NOT_FOUND);
58
+					break;
59
+
60
+				case HttpResponse::HTTP_SERVICE_UNAVAILABLE:
61
+					$result = static::error($exception, static::TYPE_HTTP_SERVICE_UNAVAILABLE_KEY,
62
+						BaseApiCodes::EX_HTTP_SERVICE_UNAVAILABLE(), HttpResponse::HTTP_SERVICE_UNAVAILABLE);
63
+					break;
64
+
65
+				case HttpResponse::HTTP_UNAUTHORIZED:
66
+					$result = static::error($exception, static::TYPE_HTTP_UNAUTHORIZED_KEY,
67
+						BaseApiCodes::EX_AUTHENTICATION_EXCEPTION(), HttpResponse::HTTP_UNAUTHORIZED);
68
+					break;
69
+
70
+				default:
71
+					$result = static::error($exception, static::TYPE_HTTP_EXCEPTION_KEY,
72
+						BaseApiCodes::EX_HTTP_EXCEPTION(), HttpResponse::HTTP_BAD_REQUEST);
73
+					break;
74
+			}
75
+		} elseif ($exception instanceof ValidationException) {
76
+			$result = static::error($exception, static::TYPE_VALIDATION_EXCEPTION_KEY,
77
+				BaseApiCodes::EX_VALIDATION_EXCEPTION(), HttpResponse::HTTP_BAD_REQUEST);
78
+		}
79
+
80
+		if ($result === null) {
81
+			$result = static::error($exception, static::TYPE_UNCAUGHT_EXCEPTION_KEY,
82
+				BaseApiCodes::EX_UNCAUGHT_EXCEPTION(), HttpResponse::HTTP_INTERNAL_SERVER_ERROR);
83
+		}
84
+
85
+		return $result;
86
+	}
87
+
88
+	/**
89
+	 * Convert an authentication exception into an unauthenticated response.
90
+	 *
91
+	 * @param \Illuminate\Http\Request                 $request
92
+	 * @param \Illuminate\Auth\AuthenticationException $exception
93
+	 *
94
+	 * @return HttpResponse
95
+	 */
96
+	protected function unauthenticated(/** @scrutinizer ignore-unused */ $request,
97
+																		 AuthenticationException $exception): HttpResponse
98
+	{
99
+		return static::error($exception, 'authentication_exception', BaseApiCodes::EX_AUTHENTICATION_EXCEPTION());
100
+	}
101
+
102
+	/**
103
+	 * Process singe error and produce valid API response
104
+	 *
105
+	 * @param Exception $exception            Exception to be processed
106
+	 * @param string    $exception_config_key Category of the exception
107
+	 * @param integer   $fallback_api_code    API code to return
108
+	 * @param integer   $fallback_http_code   HTTP code to return
109
+	 *
110
+	 * @return HttpResponse
111
+	 */
112
+	protected static function error(Exception $exception, $exception_config_key, $fallback_api_code,
113
+									$fallback_http_code = ResponseBuilder::DEFAULT_HTTP_CODE_ERROR): HttpResponse
114
+	{
115
+		// common prefix for config key
116
+		$base_key = sprintf('%s.exception', ResponseBuilder::CONF_EXCEPTION_HANDLER_KEY);
117
+
118
+		// get API and HTTP codes from exception handler config or use fallback values if no such
119
+		// config fields are set.
120
+		$api_code = Config::get("{$base_key}.{$exception_config_key}.code", $fallback_api_code);
121
+		$http_code = Config::get("{$base_key}.{$exception_config_key}.http_code", $fallback_http_code);
122
+
123
+		// check if we now have valid HTTP error code for this case or need to make one up.
124
+		if ($http_code < ResponseBuilder::ERROR_HTTP_CODE_MIN) {
125
+			// no code, let's try to get the exception status
126
+			$http_code = ($exception instanceof \Symfony\Component\HttpKernel\Exception\HttpException)
127
+				? $exception->getStatusCode()
128
+				: $exception->getCode();
129
+		}
130
+
131
+		// can it be considered valid HTTP error code?
132
+		if ($http_code < ResponseBuilder::ERROR_HTTP_CODE_MIN) {
133
+			$http_code = $fallback_http_code;
134
+		}
135
+
136
+		// let's figure out what event we are handling now
137
+		$known_codes = [
138
+			self::TYPE_HTTP_NOT_FOUND_KEY           => BaseApiCodes::EX_HTTP_NOT_FOUND(),
139
+			self::TYPE_HTTP_SERVICE_UNAVAILABLE_KEY => BaseApiCodes::EX_HTTP_SERVICE_UNAVAILABLE(),
140
+			self::TYPE_UNCAUGHT_EXCEPTION_KEY       => BaseApiCodes::EX_UNCAUGHT_EXCEPTION(),
141
+			self::TYPE_AUTHENTICATION_EXCEPTION_KEY => BaseApiCodes::EX_AUTHENTICATION_EXCEPTION(),
142
+			self::TYPE_VALIDATION_EXCEPTION_KEY     => BaseApiCodes::EX_VALIDATION_EXCEPTION(),
143
+			self::TYPE_HTTP_EXCEPTION_KEY           => BaseApiCodes::EX_HTTP_EXCEPTION(),
144
+		];
145
+		$base_api_code = BaseApiCodes::NO_ERROR_MESSAGE();
146
+		foreach ($known_codes as $item_config_key => $item_api_code) {
147
+			if ($api_code === Config::get("{$base_key}.{$item_config_key}.code", $item_api_code)) {
148
+				$base_api_code = $api_code;
149
+				break;
150
+			}
151
+		}
152
+
153
+		/** @var array|null $data Optional payload to return */
154
+		$data = null;
155
+		if ($api_code === Config::get("{$base_key}.validation_exception.code", BaseApiCodes::EX_VALIDATION_EXCEPTION())) {
156
+			/** @var ValidationException $exception */
157
+			$data = [ResponseBuilder::KEY_MESSAGES => $exception->validator->errors()->messages()];
158
+		}
159
+
160
+		$key = BaseApiCodes::getCodeMessageKey($api_code) ?? BaseApiCodes::getCodeMessageKey($base_api_code);
161
+
162
+		// let's build error error_message
163
+		$error_message = $exception->getMessage();
164
+
165
+		// if we do not have any error_message in the hand yet, we need to fall back to built-in string configured
166
+		// for this particular exception.
167
+		if ($error_message === '') {
168
+			$error_message = Lang::get($key, [
169
+				'api_code' => $api_code,
170 170
 				'message'  => '???',
171
-            ]);
172
-        }
173
-
174
-        // if we have trace data debugging enabled, let's gather some debug
175
-        // info and add to the response.
176
-        $trace_data = null;
177
-        if (Config::get(ResponseBuilder::CONF_KEY_DEBUG_EX_TRACE_ENABLED, false)) {
178
-            $trace_data = [
179
-                Config::get(ResponseBuilder::CONF_KEY_DEBUG_EX_TRACE_KEY, ResponseBuilder::KEY_TRACE) => [
180
-                    ResponseBuilder::KEY_CLASS => get_class($exception),
181
-                    ResponseBuilder::KEY_FILE  => $exception->getFile(),
182
-                    ResponseBuilder::KEY_LINE  => $exception->getLine(),
183
-                ],
184
-            ];
185
-        }
186
-
187
-        return ResponseBuilder::errorWithMessageAndDataAndDebug($api_code, $error_message, $data,
188
-            $http_code, null, $trace_data);
189
-    }
171
+			]);
172
+		}
173
+
174
+		// if we have trace data debugging enabled, let's gather some debug
175
+		// info and add to the response.
176
+		$trace_data = null;
177
+		if (Config::get(ResponseBuilder::CONF_KEY_DEBUG_EX_TRACE_ENABLED, false)) {
178
+			$trace_data = [
179
+				Config::get(ResponseBuilder::CONF_KEY_DEBUG_EX_TRACE_KEY, ResponseBuilder::KEY_TRACE) => [
180
+					ResponseBuilder::KEY_CLASS => get_class($exception),
181
+					ResponseBuilder::KEY_FILE  => $exception->getFile(),
182
+					ResponseBuilder::KEY_LINE  => $exception->getLine(),
183
+				],
184
+			];
185
+		}
186
+
187
+		return ResponseBuilder::errorWithMessageAndDataAndDebug($api_code, $error_message, $data,
188
+			$http_code, null, $trace_data);
189
+	}
190 190
 
191 191
 }
Please login to merge, or discard this patch.