Passed
Branch dev (67e3d9)
by Marcin
04:24 queued 01:31
created
src/ResponseBuilder.php 1 patch
Indentation   +330 added lines, -330 removed lines patch added patch discarded remove patch
@@ -25,337 +25,337 @@
 block discarded – undo
25 25
 class ResponseBuilder extends ResponseBuilderBase
26 26
 {
27 27
 
28
-    /** @var bool */
29
-    protected $success = false;
30
-
31
-    /** @var int */
32
-    protected $api_code;
33
-
34
-    /** @var int|null */
35
-    protected $http_code = null;
36
-
37
-    /** @var mixed */
38
-    protected $data = null;
39
-
40
-    /** @var string */
41
-    protected $message = null;
42
-
43
-    /** @var array */
44
-    protected $placeholders = [];
45
-
46
-    /** @var int|null */
47
-    protected $json_opts = null;
48
-
49
-    /** @var array */
50
-    protected $debug_data = [];
51
-
52
-    /** @var array */
53
-    protected $http_headers = [];
54
-
55
-    // -----------------------------------------------------------------------------------------------------------
56
-
57
-    /**
58
-     * Private constructor. Use asSuccess() and asError() static methods to obtain instance of Builder.
59
-     *
60
-     * @param bool $success
61
-     * @param int  $api_code
62
-     */
63
-    protected function __construct(bool $success, int $api_code)
64
-    {
65
-        $this->success = $success;
66
-        $this->api_code = $api_code;
67
-    }
68
-
69
-    // -----------------------------------------------------------------------------------------------------------
70
-
71
-    /**
72
-     * Returns success
73
-     *
74
-     * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
75
-     *                                         of the JSON response, single supported object or @null if there's no
76
-     *                                         to be returned.
77
-     * @param integer|null      $api_code      API code to be returned or @null to use value of BaseApiCodes::OK().
78
-     * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
79
-     *                                         substitution or @null if none.
80
-     * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
81
-     *                                         for default DEFAULT_HTTP_CODE_OK.
82
-     * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
83
-     *                                         options or pass @null to use value from your config (or defaults).
84
-     *
85
-     * @return HttpResponse
86
-     */
87
-    public static function success($data = null, $api_code = null, array $placeholders = null,
88
-                                   int $http_code = null, int $json_opts = null): HttpResponse
89
-    {
90
-        return ResponseBuilder::asSuccess($api_code)
91
-            ->withData($data)
92
-            ->withPlaceholders($placeholders)
93
-            ->withHttpCode($http_code)
94
-            ->withJsonOptions($json_opts)
95
-            ->build();
96
-    }
97
-
98
-    /**
99
-     * Builds error Response object. Supports optional arguments passed to Lang::get() if associated error
100
-     * message uses placeholders as well as return data payload
101
-     *
102
-     * @param integer           $api_code      Your API code to be returned with the response object.
103
-     * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
104
-     *                                         substitution or @null if none.
105
-     * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
106
-     *                                         of the JSON response, single supported object or @null if there's no
107
-     *                                         to be returned.
108
-     * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
109
-     *                                         for default DEFAULT_HTTP_CODE_ERROR.
110
-     * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
111
-     *                                         options or pass @null to use value from your config (or defaults).
112
-     *
113
-     * @return HttpResponse
114
-     */
115
-    public static function error(int $api_code, array $placeholders = null, $data = null, int $http_code = null,
116
-                                 int $json_opts = null): HttpResponse
117
-    {
118
-        return ResponseBuilder::asError($api_code)
119
-            ->withPlaceholders($placeholders)
120
-            ->withData($data)
121
-            ->withHttpCode($http_code)
122
-            ->withJsonOptions($json_opts)
123
-            ->build();
124
-    }
28
+	/** @var bool */
29
+	protected $success = false;
30
+
31
+	/** @var int */
32
+	protected $api_code;
33
+
34
+	/** @var int|null */
35
+	protected $http_code = null;
36
+
37
+	/** @var mixed */
38
+	protected $data = null;
39
+
40
+	/** @var string */
41
+	protected $message = null;
42
+
43
+	/** @var array */
44
+	protected $placeholders = [];
45
+
46
+	/** @var int|null */
47
+	protected $json_opts = null;
48
+
49
+	/** @var array */
50
+	protected $debug_data = [];
51
+
52
+	/** @var array */
53
+	protected $http_headers = [];
54
+
55
+	// -----------------------------------------------------------------------------------------------------------
56
+
57
+	/**
58
+	 * Private constructor. Use asSuccess() and asError() static methods to obtain instance of Builder.
59
+	 *
60
+	 * @param bool $success
61
+	 * @param int  $api_code
62
+	 */
63
+	protected function __construct(bool $success, int $api_code)
64
+	{
65
+		$this->success = $success;
66
+		$this->api_code = $api_code;
67
+	}
68
+
69
+	// -----------------------------------------------------------------------------------------------------------
70
+
71
+	/**
72
+	 * Returns success
73
+	 *
74
+	 * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
75
+	 *                                         of the JSON response, single supported object or @null if there's no
76
+	 *                                         to be returned.
77
+	 * @param integer|null      $api_code      API code to be returned or @null to use value of BaseApiCodes::OK().
78
+	 * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
79
+	 *                                         substitution or @null if none.
80
+	 * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
81
+	 *                                         for default DEFAULT_HTTP_CODE_OK.
82
+	 * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
83
+	 *                                         options or pass @null to use value from your config (or defaults).
84
+	 *
85
+	 * @return HttpResponse
86
+	 */
87
+	public static function success($data = null, $api_code = null, array $placeholders = null,
88
+								   int $http_code = null, int $json_opts = null): HttpResponse
89
+	{
90
+		return ResponseBuilder::asSuccess($api_code)
91
+			->withData($data)
92
+			->withPlaceholders($placeholders)
93
+			->withHttpCode($http_code)
94
+			->withJsonOptions($json_opts)
95
+			->build();
96
+	}
97
+
98
+	/**
99
+	 * Builds error Response object. Supports optional arguments passed to Lang::get() if associated error
100
+	 * message uses placeholders as well as return data payload
101
+	 *
102
+	 * @param integer           $api_code      Your API code to be returned with the response object.
103
+	 * @param array|null        $placeholders  Placeholders passed to Lang::get() for message placeholders
104
+	 *                                         substitution or @null if none.
105
+	 * @param object|array|null $data          Array of primitives and supported objects to be returned in 'data' node
106
+	 *                                         of the JSON response, single supported object or @null if there's no
107
+	 *                                         to be returned.
108
+	 * @param integer|null      $http_code     HTTP code to be used for HttpResponse sent or @null
109
+	 *                                         for default DEFAULT_HTTP_CODE_ERROR.
110
+	 * @param integer|null      $json_opts     See http://php.net/manual/en/function.json-encode.php for supported
111
+	 *                                         options or pass @null to use value from your config (or defaults).
112
+	 *
113
+	 * @return HttpResponse
114
+	 */
115
+	public static function error(int $api_code, array $placeholders = null, $data = null, int $http_code = null,
116
+								 int $json_opts = null): HttpResponse
117
+	{
118
+		return ResponseBuilder::asError($api_code)
119
+			->withPlaceholders($placeholders)
120
+			->withData($data)
121
+			->withHttpCode($http_code)
122
+			->withJsonOptions($json_opts)
123
+			->build();
124
+	}
125 125
 
126 126
 // -----------------------------------------------------------------------------------------------------------
127 127
 
128
-    public static function asSuccess(int $api_code = null): self
129
-    {
130
-        return new self(true, $api_code ?? BaseApiCodes::OK());
131
-    }
132
-
133
-    public static function asError(int $api_code): self
134
-    {
135
-        $code_ok = BaseApiCodes::OK();
136
-        if ($api_code !== $code_ok) {
137
-            Validator::assertIsIntRange('api_code', $api_code, BaseApiCodes::getMinCode(), BaseApiCodes::getMaxCode());
138
-        }
139
-        if ($api_code === $code_ok) {
140
-            throw new \InvalidArgumentException(
141
-                "Error response cannot use api_code of value {$code_ok} which is reserved for OK");
142
-        }
143
-
144
-        return new self(false, $api_code);
145
-    }
146
-
147
-    public function withHttpCode(int $http_code = null): self
148
-    {
149
-        Validator::assertIsType('http_code', $http_code, [Validator::TYPE_INTEGER,
150
-                                                          Validator::TYPE_NULL]);
151
-        $this->http_code = $http_code;
152
-
153
-        return $this;
154
-    }
155
-
156
-    public function withData($data = null): self
157
-    {
158
-        Validator::assertIsType('data', $data, [Validator::TYPE_ARRAY,
159
-                                                Validator::TYPE_OBJECT,
160
-                                                Validator::TYPE_NULL]);
161
-        $this->data = $data;
162
-
163
-        return $this;
164
-    }
165
-
166
-    public function withJsonOptions(int $json_opts = null): self
167
-    {
168
-        Validator::assertIsType('json_opts', $json_opts, [Validator::TYPE_INTEGER,
169
-                                                          Validator::TYPE_NULL]);
170
-        $this->json_opts = $json_opts;
171
-
172
-        return $this;
173
-    }
174
-
175
-    public function withDebugData(array $debug_data = null): self
176
-    {
177
-        Validator::assertIsType('$debug_data', $debug_data, [Validator::TYPE_ARRAY,
178
-                                                             Validator::TYPE_NULL]);
179
-        $this->debug_data = $debug_data;
180
-
181
-        return $this;
182
-    }
183
-
184
-    public function withMessage(string $msg = null): self
185
-    {
186
-        Validator::assertIsType('message', $msg, [Validator::TYPE_STRING,
187
-                                                  Validator::TYPE_NULL]);
188
-        $this->message = $msg;
189
-
190
-        return $this;
191
-    }
192
-
193
-    public function withPlaceholders(array $placeholders = null): self
194
-    {
195
-        $this->placeholders = $placeholders;
196
-
197
-        return $this;
198
-    }
199
-
200
-    public function withHttpHeaders(array $http_headers = null): self
201
-    {
202
-        $this->http_headers = $http_headers ?? [];
203
-
204
-        return $this;
205
-    }
206
-
207
-    public function build(): HttpResponse
208
-    {
209
-        $api_code = $this->api_code;
210
-        Validator::assertIsInt('api_code', $api_code);
211
-
212
-        $msg_or_api_code = $this->message ?? $api_code;
213
-        $http_headers = $this->http_headers ?? [];
214
-
215
-        if ($this->success) {
216
-            $api_code = $api_code ?? BaseApiCodes::OK();
217
-            $http_code = $this->http_code ?? ResponseBuilder::DEFAULT_HTTP_CODE_OK;
218
-
219
-            Validator::assertOkHttpCode($http_code);
220
-
221
-            $result = $this->make($this->success, $api_code, $msg_or_api_code, $this->data, $http_code,
222
-                $this->placeholders, $http_headers, $this->json_opts);
223
-        } else {
224
-            $http_code = $this->http_code ?? ResponseBuilder::DEFAULT_HTTP_CODE_ERROR;
225
-
226
-            Validator::assertErrorHttpCode($http_code);
227
-
228
-            $result = $this->make(false, $api_code, $msg_or_api_code, $this->data, $http_code, $this->placeholders,
229
-                $this->http_headers, $this->json_opts, $this->debug_data);
230
-        }
231
-
232
-        return $result;
233
-    }
234
-
235
-
236
-    /**
237
-     * @param boolean           $success         @true if response reports successful operation, @false otherwise.
238
-     * @param integer           $api_code        Your API code to be returned with the response object.
239
-     * @param string|integer    $msg_or_api_code message string or valid API code to get message for
240
-     * @param object|array|null $data            optional additional data to be included in response object
241
-     * @param integer|null      $http_code       HTTP code for the HttpResponse or @null for either DEFAULT_HTTP_CODE_OK
242
-     *                                           or DEFAULT_HTTP_CODE_ERROR depending on the $success.
243
-     * @param array|null        $placeholders    Placeholders passed to Lang::get() for message placeholders
244
-     *                                           substitution or @null if none.
245
-     * @param array|null        $http_headers    Optional HTTP headers to be returned in the response.
246
-     * @param integer|null      $json_opts       See http://php.net/manual/en/function.json-encode.php for supported
247
-     *                                           options or pass @null to use value from your config (or defaults).
248
-     * @param array|null        $debug_data      Optional debug data array to be added to returned JSON.
249
-     *
250
-     * @return HttpResponse
251
-     *
252
-     * @throws \InvalidArgumentException If $api_code is neither a string nor valid integer code.
253
-     * @throws \InvalidArgumentException if $data is an object of class that is not configured in "classes" mapping.
254
-     *
255
-     * @noinspection MoreThanThreeArgumentsInspection
256
-     */
257
-    protected function make(bool $success, int $api_code, $msg_or_api_code, $data = null,
258
-                            int $http_code = null, array $placeholders = null, array $http_headers = null,
259
-                            int $json_opts = null, array $debug_data = null): HttpResponse
260
-    {
261
-        $http_headers = $http_headers ?? [];
262
-        $http_code = $http_code ?? ($success ? ResponseBuilder::DEFAULT_HTTP_CODE_OK : ResponseBuilder::DEFAULT_HTTP_CODE_ERROR);
263
-        $json_opts = $json_opts ?? Config::get(ResponseBuilder::CONF_KEY_ENCODING_OPTIONS, ResponseBuilder::DEFAULT_ENCODING_OPTIONS);
264
-
265
-        Validator::assertIsInt('encoding_options', $json_opts);
266
-
267
-        Validator::assertIsInt('api_code', $api_code);
268
-        if (!BaseApiCodes::isCodeValid($api_code)) {
269
-            Validator::assertIsIntRange('api_code', $api_code, BaseApiCodes::getMinCode(), BaseApiCodes::getMaxCode());
270
-        }
271
-
272
-        return Response::json(
273
-            $this->buildResponse($success, $api_code, $msg_or_api_code, $placeholders, $data, $debug_data),
274
-            $http_code, $http_headers, $json_opts);
275
-    }
276
-
277
-    /**
278
-     * Creates standardised API response array. This is final method called in the whole pipeline before we
279
-     * return final JSON back to client. If you want to manipulate your response, this is the place to do that.
280
-     * If you set APP_DEBUG to true, 'code_hex' field will be additionally added to reported JSON for easier
281
-     * manual debugging.
282
-     *
283
-     * @param boolean           $success         @true if response reports successful operation, @false otherwise.
284
-     * @param integer           $api_code        Your API code to be returned with the response object.
285
-     * @param string|integer    $msg_or_api_code Message string or valid API code to get message for.
286
-     * @param array|null        $placeholders    Placeholders passed to Lang::get() for message placeholders
287
-     *                                           substitution or @null if none.
288
-     * @param object|array|null $data            API response data if any
289
-     * @param array|null        $debug_data      optional debug data array to be added to returned JSON.
290
-     *
291
-     * @return array response ready to be encoded as json and sent back to client
292
-     *
293
-     * @throws \RuntimeException in case of missing or invalid "classes" mapping configuration
294
-     */
295
-    protected function buildResponse(bool $success, int $api_code,
296
-                                     $msg_or_api_code, array $placeholders = null,
297
-                                     $data = null, array $debug_data = null): array
298
-    {
299
-        // ensure $data is either @null, array or object of class with configured mapping.
300
-        $data = (new Converter())->convert($data);
301
-        if ($data !== null && !is_object($data)) {
302
-            // ensure we get object in final JSON structure in data node
303
-            $data = (object)$data;
304
-        }
305
-
306
-        // get human readable message for API code or use message string (if given instead of API code)
307
-        if (is_int($msg_or_api_code)) {
308
-            $message = $this->getMessageForApiCode($success, $msg_or_api_code, $placeholders);
309
-        } else {
310
-            Validator::assertIsString('message', $msg_or_api_code);
311
-            $message = $msg_or_api_code;
312
-        }
313
-
314
-        /** @noinspection PhpUndefinedClassInspection */
315
-        $response = [
316
-            ResponseBuilder::KEY_SUCCESS => $success,
317
-            ResponseBuilder::KEY_CODE    => $api_code,
318
-            ResponseBuilder::KEY_LOCALE  => \App::getLocale(),
319
-            ResponseBuilder::KEY_MESSAGE => $message,
320
-            ResponseBuilder::KEY_DATA    => $data,
321
-        ];
322
-
323
-        if ($debug_data !== null) {
324
-            $debug_key = Config::get(ResponseBuilder::CONF_KEY_DEBUG_DEBUG_KEY, ResponseBuilder::KEY_DEBUG);
325
-            $response[ $debug_key ] = $debug_data;
326
-        }
327
-
328
-        return $response;
329
-    }
330
-
331
-    /**
332
-     * If $msg_or_api_code is integer value, returns human readable message associated with that code (with
333
-     * fallback to built-in default string if no api code mapping is set. If $msg_or_api_code is a string,
334
-     * returns it unaltered.
335
-     *
336
-     * @param boolean    $success      @true if response reports successful operation, @false otherwise.
337
-     * @param integer    $api_code     Your API code to be returned with the response object.
338
-     * @param array|null $placeholders Placeholders passed to Lang::get() for message placeholders
339
-     *                                 substitution or @null if none.
340
-     *
341
-     * @return string
342
-     */
343
-    protected function getMessageForApiCode(bool $success, int $api_code, array $placeholders = null): string
344
-    {
345
-        // We got integer value here not a message string, so we need to check if we have the mapping for
346
-        // this string already configured.
347
-        $key = BaseApiCodes::getCodeMessageKey($api_code);
348
-        if ($key === null) {
349
-            // nope, let's get the default one instead, based of
350
-            $fallback_code = $success ? BaseApiCodes::OK() : BaseApiCodes::NO_ERROR_MESSAGE();
351
-            $key = BaseApiCodes::getCodeMessageKey($fallback_code);
352
-        }
353
-
354
-        $placeholders = $placeholders ?? [];
355
-        if (!array_key_exists('api_code', $placeholders)) {
356
-            $placeholders['api_code'] = $api_code;
357
-        }
358
-
359
-        return \Lang::get($key, $placeholders);
360
-    }
128
+	public static function asSuccess(int $api_code = null): self
129
+	{
130
+		return new self(true, $api_code ?? BaseApiCodes::OK());
131
+	}
132
+
133
+	public static function asError(int $api_code): self
134
+	{
135
+		$code_ok = BaseApiCodes::OK();
136
+		if ($api_code !== $code_ok) {
137
+			Validator::assertIsIntRange('api_code', $api_code, BaseApiCodes::getMinCode(), BaseApiCodes::getMaxCode());
138
+		}
139
+		if ($api_code === $code_ok) {
140
+			throw new \InvalidArgumentException(
141
+				"Error response cannot use api_code of value {$code_ok} which is reserved for OK");
142
+		}
143
+
144
+		return new self(false, $api_code);
145
+	}
146
+
147
+	public function withHttpCode(int $http_code = null): self
148
+	{
149
+		Validator::assertIsType('http_code', $http_code, [Validator::TYPE_INTEGER,
150
+														  Validator::TYPE_NULL]);
151
+		$this->http_code = $http_code;
152
+
153
+		return $this;
154
+	}
155
+
156
+	public function withData($data = null): self
157
+	{
158
+		Validator::assertIsType('data', $data, [Validator::TYPE_ARRAY,
159
+												Validator::TYPE_OBJECT,
160
+												Validator::TYPE_NULL]);
161
+		$this->data = $data;
162
+
163
+		return $this;
164
+	}
165
+
166
+	public function withJsonOptions(int $json_opts = null): self
167
+	{
168
+		Validator::assertIsType('json_opts', $json_opts, [Validator::TYPE_INTEGER,
169
+														  Validator::TYPE_NULL]);
170
+		$this->json_opts = $json_opts;
171
+
172
+		return $this;
173
+	}
174
+
175
+	public function withDebugData(array $debug_data = null): self
176
+	{
177
+		Validator::assertIsType('$debug_data', $debug_data, [Validator::TYPE_ARRAY,
178
+															 Validator::TYPE_NULL]);
179
+		$this->debug_data = $debug_data;
180
+
181
+		return $this;
182
+	}
183
+
184
+	public function withMessage(string $msg = null): self
185
+	{
186
+		Validator::assertIsType('message', $msg, [Validator::TYPE_STRING,
187
+												  Validator::TYPE_NULL]);
188
+		$this->message = $msg;
189
+
190
+		return $this;
191
+	}
192
+
193
+	public function withPlaceholders(array $placeholders = null): self
194
+	{
195
+		$this->placeholders = $placeholders;
196
+
197
+		return $this;
198
+	}
199
+
200
+	public function withHttpHeaders(array $http_headers = null): self
201
+	{
202
+		$this->http_headers = $http_headers ?? [];
203
+
204
+		return $this;
205
+	}
206
+
207
+	public function build(): HttpResponse
208
+	{
209
+		$api_code = $this->api_code;
210
+		Validator::assertIsInt('api_code', $api_code);
211
+
212
+		$msg_or_api_code = $this->message ?? $api_code;
213
+		$http_headers = $this->http_headers ?? [];
214
+
215
+		if ($this->success) {
216
+			$api_code = $api_code ?? BaseApiCodes::OK();
217
+			$http_code = $this->http_code ?? ResponseBuilder::DEFAULT_HTTP_CODE_OK;
218
+
219
+			Validator::assertOkHttpCode($http_code);
220
+
221
+			$result = $this->make($this->success, $api_code, $msg_or_api_code, $this->data, $http_code,
222
+				$this->placeholders, $http_headers, $this->json_opts);
223
+		} else {
224
+			$http_code = $this->http_code ?? ResponseBuilder::DEFAULT_HTTP_CODE_ERROR;
225
+
226
+			Validator::assertErrorHttpCode($http_code);
227
+
228
+			$result = $this->make(false, $api_code, $msg_or_api_code, $this->data, $http_code, $this->placeholders,
229
+				$this->http_headers, $this->json_opts, $this->debug_data);
230
+		}
231
+
232
+		return $result;
233
+	}
234
+
235
+
236
+	/**
237
+	 * @param boolean           $success         @true if response reports successful operation, @false otherwise.
238
+	 * @param integer           $api_code        Your API code to be returned with the response object.
239
+	 * @param string|integer    $msg_or_api_code message string or valid API code to get message for
240
+	 * @param object|array|null $data            optional additional data to be included in response object
241
+	 * @param integer|null      $http_code       HTTP code for the HttpResponse or @null for either DEFAULT_HTTP_CODE_OK
242
+	 *                                           or DEFAULT_HTTP_CODE_ERROR depending on the $success.
243
+	 * @param array|null        $placeholders    Placeholders passed to Lang::get() for message placeholders
244
+	 *                                           substitution or @null if none.
245
+	 * @param array|null        $http_headers    Optional HTTP headers to be returned in the response.
246
+	 * @param integer|null      $json_opts       See http://php.net/manual/en/function.json-encode.php for supported
247
+	 *                                           options or pass @null to use value from your config (or defaults).
248
+	 * @param array|null        $debug_data      Optional debug data array to be added to returned JSON.
249
+	 *
250
+	 * @return HttpResponse
251
+	 *
252
+	 * @throws \InvalidArgumentException If $api_code is neither a string nor valid integer code.
253
+	 * @throws \InvalidArgumentException if $data is an object of class that is not configured in "classes" mapping.
254
+	 *
255
+	 * @noinspection MoreThanThreeArgumentsInspection
256
+	 */
257
+	protected function make(bool $success, int $api_code, $msg_or_api_code, $data = null,
258
+							int $http_code = null, array $placeholders = null, array $http_headers = null,
259
+							int $json_opts = null, array $debug_data = null): HttpResponse
260
+	{
261
+		$http_headers = $http_headers ?? [];
262
+		$http_code = $http_code ?? ($success ? ResponseBuilder::DEFAULT_HTTP_CODE_OK : ResponseBuilder::DEFAULT_HTTP_CODE_ERROR);
263
+		$json_opts = $json_opts ?? Config::get(ResponseBuilder::CONF_KEY_ENCODING_OPTIONS, ResponseBuilder::DEFAULT_ENCODING_OPTIONS);
264
+
265
+		Validator::assertIsInt('encoding_options', $json_opts);
266
+
267
+		Validator::assertIsInt('api_code', $api_code);
268
+		if (!BaseApiCodes::isCodeValid($api_code)) {
269
+			Validator::assertIsIntRange('api_code', $api_code, BaseApiCodes::getMinCode(), BaseApiCodes::getMaxCode());
270
+		}
271
+
272
+		return Response::json(
273
+			$this->buildResponse($success, $api_code, $msg_or_api_code, $placeholders, $data, $debug_data),
274
+			$http_code, $http_headers, $json_opts);
275
+	}
276
+
277
+	/**
278
+	 * Creates standardised API response array. This is final method called in the whole pipeline before we
279
+	 * return final JSON back to client. If you want to manipulate your response, this is the place to do that.
280
+	 * If you set APP_DEBUG to true, 'code_hex' field will be additionally added to reported JSON for easier
281
+	 * manual debugging.
282
+	 *
283
+	 * @param boolean           $success         @true if response reports successful operation, @false otherwise.
284
+	 * @param integer           $api_code        Your API code to be returned with the response object.
285
+	 * @param string|integer    $msg_or_api_code Message string or valid API code to get message for.
286
+	 * @param array|null        $placeholders    Placeholders passed to Lang::get() for message placeholders
287
+	 *                                           substitution or @null if none.
288
+	 * @param object|array|null $data            API response data if any
289
+	 * @param array|null        $debug_data      optional debug data array to be added to returned JSON.
290
+	 *
291
+	 * @return array response ready to be encoded as json and sent back to client
292
+	 *
293
+	 * @throws \RuntimeException in case of missing or invalid "classes" mapping configuration
294
+	 */
295
+	protected function buildResponse(bool $success, int $api_code,
296
+									 $msg_or_api_code, array $placeholders = null,
297
+									 $data = null, array $debug_data = null): array
298
+	{
299
+		// ensure $data is either @null, array or object of class with configured mapping.
300
+		$data = (new Converter())->convert($data);
301
+		if ($data !== null && !is_object($data)) {
302
+			// ensure we get object in final JSON structure in data node
303
+			$data = (object)$data;
304
+		}
305
+
306
+		// get human readable message for API code or use message string (if given instead of API code)
307
+		if (is_int($msg_or_api_code)) {
308
+			$message = $this->getMessageForApiCode($success, $msg_or_api_code, $placeholders);
309
+		} else {
310
+			Validator::assertIsString('message', $msg_or_api_code);
311
+			$message = $msg_or_api_code;
312
+		}
313
+
314
+		/** @noinspection PhpUndefinedClassInspection */
315
+		$response = [
316
+			ResponseBuilder::KEY_SUCCESS => $success,
317
+			ResponseBuilder::KEY_CODE    => $api_code,
318
+			ResponseBuilder::KEY_LOCALE  => \App::getLocale(),
319
+			ResponseBuilder::KEY_MESSAGE => $message,
320
+			ResponseBuilder::KEY_DATA    => $data,
321
+		];
322
+
323
+		if ($debug_data !== null) {
324
+			$debug_key = Config::get(ResponseBuilder::CONF_KEY_DEBUG_DEBUG_KEY, ResponseBuilder::KEY_DEBUG);
325
+			$response[ $debug_key ] = $debug_data;
326
+		}
327
+
328
+		return $response;
329
+	}
330
+
331
+	/**
332
+	 * If $msg_or_api_code is integer value, returns human readable message associated with that code (with
333
+	 * fallback to built-in default string if no api code mapping is set. If $msg_or_api_code is a string,
334
+	 * returns it unaltered.
335
+	 *
336
+	 * @param boolean    $success      @true if response reports successful operation, @false otherwise.
337
+	 * @param integer    $api_code     Your API code to be returned with the response object.
338
+	 * @param array|null $placeholders Placeholders passed to Lang::get() for message placeholders
339
+	 *                                 substitution or @null if none.
340
+	 *
341
+	 * @return string
342
+	 */
343
+	protected function getMessageForApiCode(bool $success, int $api_code, array $placeholders = null): string
344
+	{
345
+		// We got integer value here not a message string, so we need to check if we have the mapping for
346
+		// this string already configured.
347
+		$key = BaseApiCodes::getCodeMessageKey($api_code);
348
+		if ($key === null) {
349
+			// nope, let's get the default one instead, based of
350
+			$fallback_code = $success ? BaseApiCodes::OK() : BaseApiCodes::NO_ERROR_MESSAGE();
351
+			$key = BaseApiCodes::getCodeMessageKey($fallback_code);
352
+		}
353
+
354
+		$placeholders = $placeholders ?? [];
355
+		if (!array_key_exists('api_code', $placeholders)) {
356
+			$placeholders['api_code'] = $api_code;
357
+		}
358
+
359
+		return \Lang::get($key, $placeholders);
360
+	}
361 361
 }
Please login to merge, or discard this patch.
src/ExceptionHandlerHelper.php 2 patches
Indentation   +222 added lines, -222 removed lines patch added patch discarded remove patch
@@ -27,227 +27,227 @@
 block discarded – undo
27 27
  */
28 28
 class ExceptionHandlerHelper
29 29
 {
30
-    /**
31
-     * Render an exception into valid API response.
32
-     *
33
-     * @param \Illuminate\Http\Request $request Request object
34
-     * @param \Exception               $ex      Exception
35
-     *
36
-     * @return HttpResponse
37
-     */
38
-    public static function render(/** @scrutinizer ignore-unused */ $request, Exception $ex): HttpResponse
39
-    {
40
-        $result = null;
41
-        $cfg = static::getExceptionHandlerConfig()['map'];
42
-
43
-        if ($ex instanceof HttpException) {
44
-            // Check if we have any exception configuration for this particular HTTP status code.
45
-            // This confing entry is guaranted to exist (at least 'default'). Enforced by tests.
46
-            $http_code = $ex->getStatusCode();
47
-            $ex_cfg = $cfg[ HttpException::class ][ $http_code ] ?? null;
48
-            $ex_cfg = $ex_cfg ?? $cfg[ HttpException::class ]['default'];
49
-            $result = self::processException($ex, $ex_cfg, $http_code);
50
-        } elseif ($ex instanceof ValidationException) {
51
-            // This entry is guaranted to exist. Enforced by tests.
52
-            $http_code = HttpResponse::HTTP_UNPROCESSABLE_ENTITY;
53
-            $result = self::processException($ex, $cfg[ HttpException::class ][ $http_code ], $http_code);
54
-        }
55
-
56
-        if ($result === null) {
57
-            // This entry is guaranted to exist. Enforced by tests.
58
-            $result = self::processException($ex, $cfg['default'], HttpResponse::HTTP_INTERNAL_SERVER_ERROR);
59
-        }
60
-
61
-        return $result;
62
-    }
63
-
64
-    /**
65
-     * Handles given exception and produces valid HTTP response object.
66
-     *
67
-     * @param \Exception $ex                 Exception to be handled.
68
-     * @param array      $ex_cfg             ExceptionHandler's config excerpt related to $ex exception type.
69
-     * @param int        $fallback_http_code HTTP code to be assigned to produced $ex related response in
70
-     *                                       case configuration array lacks own `http_code` value.
71
-     *
72
-     * @return \Symfony\Component\HttpFoundation\Response
73
-     */
74
-    protected static function processException(\Exception $ex, array $ex_cfg, int $fallback_http_code)
75
-    {
76
-        $api_code = $ex_cfg['api_code'];
77
-        $http_code = $ex_cfg['http_code'] ?? $fallback_http_code;
78
-        $msg_key = $ex_cfg['msg_key'] ?? null;
79
-        $msg_enforce = $ex_cfg['msg_enforce'] ?? false;
80
-
81
-        // No message key, let's get exception message and if there's nothing useful, fallback to built-in one.
82
-        $msg = $ex->getMessage();
83
-        $placeholders = [
84
-            'api_code' => $api_code,
85
-            'message'  => ($msg !== '') ? $msg : '???',
86
-        ];
87
-
88
-        // shall we enforce error message?
89
-        if ($msg_enforce) {
90
-            // yes, please.
91
-            if ($msg_key === null) {
92
-                // there's no msg_key configured for this exact code, so let's obtain our default message
93
-                $msg = ($msg_key === null) ? static::getErrorMessageForException($ex, $http_code, $placeholders)
94
-                    : Lang::get($msg_key, $placeholders);
95
-            }
96
-        } else {
97
-            // nothing enforced, handling pipeline: ex_message -> user_defined_msg -> http_ex -> default
98
-            if ($msg === '') {
99
-                $msg = ($msg_key === null) ? static::getErrorMessageForException($ex, $http_code, $placeholders)
100
-                    : Lang::get($msg_key, $placeholders);
101
-            }
102
-        }
103
-
104
-        // Lets' try to build the error response with what we have now
105
-        return static::error($ex, $api_code, $http_code, $msg);
106
-    }
107
-
108
-    /**
109
-     * Returns error message for given exception. If exception message is empty, then falls back to
110
-     * `default` handler either for HttpException (if $ex is instance of it), or generic `default`
111
-     * config.
112
-     *
113
-     * @param \Exception $ex
114
-     * @param int        $http_code
115
-     * @param array      $placeholders
116
-     *
117
-     * @return string
118
-     */
119
-    protected static function getErrorMessageForException(\Exception $ex, int $http_code, array $placeholders): string
120
-    {
121
-        // exception message is uselss, lets go deeper
122
-        if ($ex instanceof HttpException) {
123
-            $error_message = Lang::get("response-builder::builder.http_{$http_code}", $placeholders);
124
-        } else {
125
-            // Still got nothing? Fall back to built-in generic message for this type of exception.
126
-            $key = BaseApiCodes::getCodeMessageKey(($ex instanceof HttpException)
127
-                ? BaseApiCodes::EX_HTTP_EXCEPTION() : BaseApiCodes::NO_ERROR_MESSAGE());
128
-            $error_message = Lang::get($key, $placeholders);
129
-        }
130
-
131
-        return $error_message;
132
-    }
133
-
134
-    /**
135
-     * Convert an authentication exception into an unauthenticated response.
136
-     *
137
-     * @param \Illuminate\Http\Request                 $request
138
-     * @param \Illuminate\Auth\AuthenticationException $exception
139
-     *
140
-     * @return HttpResponse
141
-     */
142
-    protected function unauthenticated(/** @scrutinizer ignore-unused */ $request,
143
-                                                                         AuthException $exception): HttpResponse
144
-    {
145
-        // This entry is guaranted to exist. Enforced by tests.
146
-        $http_code = HttpResponse::HTTP_UNAUTHORIZED;
147
-        $cfg = static::getExceptionHandlerConfig()['map'][ HttpException::class ][ $http_code ];
148
-
149
-        return static::processException($exception, $cfg, $http_code);
150
-    }
151
-
152
-    /**
153
-     * Process single error and produce valid API response.
154
-     *
155
-     * @param Exception $ex Exception to be handled.
156
-     * @param integer   $api_code
157
-     * @param integer   $http_code
158
-     *
159
-     * @return HttpResponse
160
-     */
161
-    protected static function error(Exception $ex,
162
-                                    int $api_code, int $http_code = null, string $error_message): HttpResponse
163
-    {
164
-        $ex_http_code = ($ex instanceof HttpException) ? $ex->getStatusCode() : $ex->getCode();
165
-        $http_code = $http_code ?? $ex_http_code;
166
-
167
-        // Check if we now have valid HTTP error code for this case or need to make one up.
168
-        // We cannot throw any exception if codes are invalid because we are in Exception Handler already.
169
-        if ($http_code < ResponseBuilder::ERROR_HTTP_CODE_MIN) {
170
-            // Not a valid code, let's try to get the exception status.
171
-            $http_code = $ex_http_code;
172
-        }
173
-        // Can it be considered a valid HTTP error code?
174
-        if ($http_code < ResponseBuilder::ERROR_HTTP_CODE_MIN) {
175
-            // We now handle uncaught exception, so we cannot throw another one if there's
176
-            // something wrong with the configuration, so we try to recover and use built-in
177
-            // codes instead.
178
-            // FIXME: We should log this event as (warning or error?)
179
-            $http_code = ResponseBuilder::DEFAULT_HTTP_CODE_ERROR;
180
-        }
181
-
182
-        // If we have trace data debugging enabled, let's gather some debug info and add to the response.
183
-        $debug_data = null;
184
-        if (Config::get(ResponseBuilder::CONF_KEY_DEBUG_EX_TRACE_ENABLED, false)) {
185
-            $debug_data = [
186
-                Config::get(ResponseBuilder::CONF_KEY_DEBUG_EX_TRACE_KEY, ResponseBuilder::KEY_TRACE) => [
187
-                    ResponseBuilder::KEY_CLASS => get_class($ex),
188
-                    ResponseBuilder::KEY_FILE  => $ex->getFile(),
189
-                    ResponseBuilder::KEY_LINE  => $ex->getLine(),
190
-                ],
191
-            ];
192
-        }
193
-
194
-        // If this is ValidationException, add all the messages from MessageBag to the data node.
195
-        $data = null;
196
-        if ($ex instanceof ValidationException) {
197
-            /** @var ValidationException $ex */
198
-            $data = [ResponseBuilder::KEY_MESSAGES => $ex->validator->errors()->messages()];
199
-        }
200
-
201
-        return ResponseBuilder::asError($api_code)
202
-            ->withMessage($error_message)
203
-            ->withHttpCode($http_code)
204
-            ->withData($data)
205
-            ->withDebugData($debug_data)
206
-            ->build();
207
-    }
208
-
209
-    /**
210
-     * Returns default (built-in) exception handler config array.
211
-     *
212
-     * @return array
213
-     */
214
-    protected static function getExceptionHandlerDefaultConfig(): array
215
-    {
216
-        return [
217
-            'map' => [
218
-                HttpException::class => [
219
-                    // used by unauthenticated() to obtain api and http code for the exception
220
-                    HttpResponse::HTTP_UNAUTHORIZED         => [
221
-                        'api_code' => BaseApiCodes::EX_AUTHENTICATION_EXCEPTION(),
222
-                    ],
223
-                    // Required by ValidationException handler
224
-                    HttpResponse::HTTP_UNPROCESSABLE_ENTITY => [
225
-                        'api_code' => BaseApiCodes::EX_VALIDATION_EXCEPTION(),
226
-                    ],
227
-                    // default handler is mandatory. `default` entry MUST have both `api_code` and `http_code` set.
228
-                    'default'                               => [
229
-                        'api_code'  => BaseApiCodes::EX_HTTP_EXCEPTION(),
230
-                        'http_code' => HttpResponse::HTTP_BAD_REQUEST,
231
-                    ],
232
-                ],
233
-                // default handler is mandatory. `default` entry MUST have both `api_code` and `http_code` set.
234
-                'default'            => [
235
-                    'api_code'  => BaseApiCodes::EX_UNCAUGHT_EXCEPTION(),
236
-                    'http_code' => HttpResponse::HTTP_INTERNAL_SERVER_ERROR,
237
-                ],
238
-            ],
239
-        ];
240
-    }
241
-
242
-    /**
243
-     * Returns ExceptionHandlerHelper configration array with user configuration merged into built-in defaults.
244
-     *
245
-     * @return array
246
-     */
247
-    protected static function getExceptionHandlerConfig(): array
248
-    {
249
-        return Util::mergeConfig(static::getExceptionHandlerDefaultConfig(),
250
-            \Config::get(ResponseBuilder::CONF_KEY_EXCEPTION_HANDLER, []));
251
-    }
30
+	/**
31
+	 * Render an exception into valid API response.
32
+	 *
33
+	 * @param \Illuminate\Http\Request $request Request object
34
+	 * @param \Exception               $ex      Exception
35
+	 *
36
+	 * @return HttpResponse
37
+	 */
38
+	public static function render(/** @scrutinizer ignore-unused */ $request, Exception $ex): HttpResponse
39
+	{
40
+		$result = null;
41
+		$cfg = static::getExceptionHandlerConfig()['map'];
42
+
43
+		if ($ex instanceof HttpException) {
44
+			// Check if we have any exception configuration for this particular HTTP status code.
45
+			// This confing entry is guaranted to exist (at least 'default'). Enforced by tests.
46
+			$http_code = $ex->getStatusCode();
47
+			$ex_cfg = $cfg[ HttpException::class ][ $http_code ] ?? null;
48
+			$ex_cfg = $ex_cfg ?? $cfg[ HttpException::class ]['default'];
49
+			$result = self::processException($ex, $ex_cfg, $http_code);
50
+		} elseif ($ex instanceof ValidationException) {
51
+			// This entry is guaranted to exist. Enforced by tests.
52
+			$http_code = HttpResponse::HTTP_UNPROCESSABLE_ENTITY;
53
+			$result = self::processException($ex, $cfg[ HttpException::class ][ $http_code ], $http_code);
54
+		}
55
+
56
+		if ($result === null) {
57
+			// This entry is guaranted to exist. Enforced by tests.
58
+			$result = self::processException($ex, $cfg['default'], HttpResponse::HTTP_INTERNAL_SERVER_ERROR);
59
+		}
60
+
61
+		return $result;
62
+	}
63
+
64
+	/**
65
+	 * Handles given exception and produces valid HTTP response object.
66
+	 *
67
+	 * @param \Exception $ex                 Exception to be handled.
68
+	 * @param array      $ex_cfg             ExceptionHandler's config excerpt related to $ex exception type.
69
+	 * @param int        $fallback_http_code HTTP code to be assigned to produced $ex related response in
70
+	 *                                       case configuration array lacks own `http_code` value.
71
+	 *
72
+	 * @return \Symfony\Component\HttpFoundation\Response
73
+	 */
74
+	protected static function processException(\Exception $ex, array $ex_cfg, int $fallback_http_code)
75
+	{
76
+		$api_code = $ex_cfg['api_code'];
77
+		$http_code = $ex_cfg['http_code'] ?? $fallback_http_code;
78
+		$msg_key = $ex_cfg['msg_key'] ?? null;
79
+		$msg_enforce = $ex_cfg['msg_enforce'] ?? false;
80
+
81
+		// No message key, let's get exception message and if there's nothing useful, fallback to built-in one.
82
+		$msg = $ex->getMessage();
83
+		$placeholders = [
84
+			'api_code' => $api_code,
85
+			'message'  => ($msg !== '') ? $msg : '???',
86
+		];
87
+
88
+		// shall we enforce error message?
89
+		if ($msg_enforce) {
90
+			// yes, please.
91
+			if ($msg_key === null) {
92
+				// there's no msg_key configured for this exact code, so let's obtain our default message
93
+				$msg = ($msg_key === null) ? static::getErrorMessageForException($ex, $http_code, $placeholders)
94
+					: Lang::get($msg_key, $placeholders);
95
+			}
96
+		} else {
97
+			// nothing enforced, handling pipeline: ex_message -> user_defined_msg -> http_ex -> default
98
+			if ($msg === '') {
99
+				$msg = ($msg_key === null) ? static::getErrorMessageForException($ex, $http_code, $placeholders)
100
+					: Lang::get($msg_key, $placeholders);
101
+			}
102
+		}
103
+
104
+		// Lets' try to build the error response with what we have now
105
+		return static::error($ex, $api_code, $http_code, $msg);
106
+	}
107
+
108
+	/**
109
+	 * Returns error message for given exception. If exception message is empty, then falls back to
110
+	 * `default` handler either for HttpException (if $ex is instance of it), or generic `default`
111
+	 * config.
112
+	 *
113
+	 * @param \Exception $ex
114
+	 * @param int        $http_code
115
+	 * @param array      $placeholders
116
+	 *
117
+	 * @return string
118
+	 */
119
+	protected static function getErrorMessageForException(\Exception $ex, int $http_code, array $placeholders): string
120
+	{
121
+		// exception message is uselss, lets go deeper
122
+		if ($ex instanceof HttpException) {
123
+			$error_message = Lang::get("response-builder::builder.http_{$http_code}", $placeholders);
124
+		} else {
125
+			// Still got nothing? Fall back to built-in generic message for this type of exception.
126
+			$key = BaseApiCodes::getCodeMessageKey(($ex instanceof HttpException)
127
+				? BaseApiCodes::EX_HTTP_EXCEPTION() : BaseApiCodes::NO_ERROR_MESSAGE());
128
+			$error_message = Lang::get($key, $placeholders);
129
+		}
130
+
131
+		return $error_message;
132
+	}
133
+
134
+	/**
135
+	 * Convert an authentication exception into an unauthenticated response.
136
+	 *
137
+	 * @param \Illuminate\Http\Request                 $request
138
+	 * @param \Illuminate\Auth\AuthenticationException $exception
139
+	 *
140
+	 * @return HttpResponse
141
+	 */
142
+	protected function unauthenticated(/** @scrutinizer ignore-unused */ $request,
143
+																		 AuthException $exception): HttpResponse
144
+	{
145
+		// This entry is guaranted to exist. Enforced by tests.
146
+		$http_code = HttpResponse::HTTP_UNAUTHORIZED;
147
+		$cfg = static::getExceptionHandlerConfig()['map'][ HttpException::class ][ $http_code ];
148
+
149
+		return static::processException($exception, $cfg, $http_code);
150
+	}
151
+
152
+	/**
153
+	 * Process single error and produce valid API response.
154
+	 *
155
+	 * @param Exception $ex Exception to be handled.
156
+	 * @param integer   $api_code
157
+	 * @param integer   $http_code
158
+	 *
159
+	 * @return HttpResponse
160
+	 */
161
+	protected static function error(Exception $ex,
162
+									int $api_code, int $http_code = null, string $error_message): HttpResponse
163
+	{
164
+		$ex_http_code = ($ex instanceof HttpException) ? $ex->getStatusCode() : $ex->getCode();
165
+		$http_code = $http_code ?? $ex_http_code;
166
+
167
+		// Check if we now have valid HTTP error code for this case or need to make one up.
168
+		// We cannot throw any exception if codes are invalid because we are in Exception Handler already.
169
+		if ($http_code < ResponseBuilder::ERROR_HTTP_CODE_MIN) {
170
+			// Not a valid code, let's try to get the exception status.
171
+			$http_code = $ex_http_code;
172
+		}
173
+		// Can it be considered a valid HTTP error code?
174
+		if ($http_code < ResponseBuilder::ERROR_HTTP_CODE_MIN) {
175
+			// We now handle uncaught exception, so we cannot throw another one if there's
176
+			// something wrong with the configuration, so we try to recover and use built-in
177
+			// codes instead.
178
+			// FIXME: We should log this event as (warning or error?)
179
+			$http_code = ResponseBuilder::DEFAULT_HTTP_CODE_ERROR;
180
+		}
181
+
182
+		// If we have trace data debugging enabled, let's gather some debug info and add to the response.
183
+		$debug_data = null;
184
+		if (Config::get(ResponseBuilder::CONF_KEY_DEBUG_EX_TRACE_ENABLED, false)) {
185
+			$debug_data = [
186
+				Config::get(ResponseBuilder::CONF_KEY_DEBUG_EX_TRACE_KEY, ResponseBuilder::KEY_TRACE) => [
187
+					ResponseBuilder::KEY_CLASS => get_class($ex),
188
+					ResponseBuilder::KEY_FILE  => $ex->getFile(),
189
+					ResponseBuilder::KEY_LINE  => $ex->getLine(),
190
+				],
191
+			];
192
+		}
193
+
194
+		// If this is ValidationException, add all the messages from MessageBag to the data node.
195
+		$data = null;
196
+		if ($ex instanceof ValidationException) {
197
+			/** @var ValidationException $ex */
198
+			$data = [ResponseBuilder::KEY_MESSAGES => $ex->validator->errors()->messages()];
199
+		}
200
+
201
+		return ResponseBuilder::asError($api_code)
202
+			->withMessage($error_message)
203
+			->withHttpCode($http_code)
204
+			->withData($data)
205
+			->withDebugData($debug_data)
206
+			->build();
207
+	}
208
+
209
+	/**
210
+	 * Returns default (built-in) exception handler config array.
211
+	 *
212
+	 * @return array
213
+	 */
214
+	protected static function getExceptionHandlerDefaultConfig(): array
215
+	{
216
+		return [
217
+			'map' => [
218
+				HttpException::class => [
219
+					// used by unauthenticated() to obtain api and http code for the exception
220
+					HttpResponse::HTTP_UNAUTHORIZED         => [
221
+						'api_code' => BaseApiCodes::EX_AUTHENTICATION_EXCEPTION(),
222
+					],
223
+					// Required by ValidationException handler
224
+					HttpResponse::HTTP_UNPROCESSABLE_ENTITY => [
225
+						'api_code' => BaseApiCodes::EX_VALIDATION_EXCEPTION(),
226
+					],
227
+					// default handler is mandatory. `default` entry MUST have both `api_code` and `http_code` set.
228
+					'default'                               => [
229
+						'api_code'  => BaseApiCodes::EX_HTTP_EXCEPTION(),
230
+						'http_code' => HttpResponse::HTTP_BAD_REQUEST,
231
+					],
232
+				],
233
+				// default handler is mandatory. `default` entry MUST have both `api_code` and `http_code` set.
234
+				'default'            => [
235
+					'api_code'  => BaseApiCodes::EX_UNCAUGHT_EXCEPTION(),
236
+					'http_code' => HttpResponse::HTTP_INTERNAL_SERVER_ERROR,
237
+				],
238
+			],
239
+		];
240
+	}
241
+
242
+	/**
243
+	 * Returns ExceptionHandlerHelper configration array with user configuration merged into built-in defaults.
244
+	 *
245
+	 * @return array
246
+	 */
247
+	protected static function getExceptionHandlerConfig(): array
248
+	{
249
+		return Util::mergeConfig(static::getExceptionHandlerDefaultConfig(),
250
+			\Config::get(ResponseBuilder::CONF_KEY_EXCEPTION_HANDLER, []));
251
+	}
252 252
 
253 253
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -44,13 +44,13 @@  discard block
 block discarded – undo
44 44
             // Check if we have any exception configuration for this particular HTTP status code.
45 45
             // This confing entry is guaranted to exist (at least 'default'). Enforced by tests.
46 46
             $http_code = $ex->getStatusCode();
47
-            $ex_cfg = $cfg[ HttpException::class ][ $http_code ] ?? null;
48
-            $ex_cfg = $ex_cfg ?? $cfg[ HttpException::class ]['default'];
47
+            $ex_cfg = $cfg[HttpException::class][$http_code] ?? null;
48
+            $ex_cfg = $ex_cfg ?? $cfg[HttpException::class]['default'];
49 49
             $result = self::processException($ex, $ex_cfg, $http_code);
50 50
         } elseif ($ex instanceof ValidationException) {
51 51
             // This entry is guaranted to exist. Enforced by tests.
52 52
             $http_code = HttpResponse::HTTP_UNPROCESSABLE_ENTITY;
53
-            $result = self::processException($ex, $cfg[ HttpException::class ][ $http_code ], $http_code);
53
+            $result = self::processException($ex, $cfg[HttpException::class][$http_code], $http_code);
54 54
         }
55 55
 
56 56
         if ($result === null) {
@@ -144,7 +144,7 @@  discard block
 block discarded – undo
144 144
     {
145 145
         // This entry is guaranted to exist. Enforced by tests.
146 146
         $http_code = HttpResponse::HTTP_UNAUTHORIZED;
147
-        $cfg = static::getExceptionHandlerConfig()['map'][ HttpException::class ][ $http_code ];
147
+        $cfg = static::getExceptionHandlerConfig()['map'][HttpException::class][$http_code];
148 148
 
149 149
         return static::processException($exception, $cfg, $http_code);
150 150
     }
Please login to merge, or discard this patch.
src/BaseApiCodes.php 1 patch
Indentation   +189 added lines, -189 removed lines patch added patch discarded remove patch
@@ -21,194 +21,194 @@
 block discarded – undo
21 21
  */
22 22
 class BaseApiCodes
23 23
 {
24
-    use ApiCodesHelpers;
25
-
26
-    /**
27
-     * protected code range - lowest code for reserved range.
28
-     *
29
-     * @var int
30
-     */
31
-    public const RESERVED_MIN_API_CODE_OFFSET = 0;
32
-
33
-    /**
34
-     * protected code range - highest code for reserved range
35
-     *
36
-     * @var int
37
-     */
38
-    public const RESERVED_MAX_API_CODE_OFFSET = 19;
39
-
40
-    /**
41
-     * built-in codes: OK
42
-     *
43
-     * @var int
44
-     */
45
-    protected const OK_OFFSET = 0;
46
-    /**
47
-     * built-in code for fallback message mapping
48
-     *
49
-     * @var int
50
-     */
51
-    protected const NO_ERROR_MESSAGE_OFFSET = 1;
52
-    /**
53
-     * built-in error code for HTTP_NOT_FOUND exception
54
-     *
55
-     * @var int
56
-     */
57
-    protected const EX_HTTP_NOT_FOUND_OFFSET = 10;
58
-    /**
59
-     * built-in error code for HTTP_SERVICE_UNAVAILABLE exception
60
-     *
61
-     * @var int
62
-     */
63
-    protected const EX_HTTP_SERVICE_UNAVAILABLE_OFFSET = 11;
64
-    /**
65
-     * built-in error code for HTTP_EXCEPTION
66
-     *
67
-     * @var int
68
-     */
69
-    protected const EX_HTTP_EXCEPTION_OFFSET = 12;
70
-    /**
71
-     * built-in error code for UNCAUGHT_EXCEPTION
72
-     *
73
-     * @var int
74
-     */
75
-    protected const EX_UNCAUGHT_EXCEPTION_OFFSET = 13;
76
-
77
-    /**
78
-     * built-in error code for \Illuminate\Auth\AuthenticationException
79
-     *
80
-     * @var int
81
-     */
82
-    protected const EX_AUTHENTICATION_EXCEPTION_OFFSET = 14;
83
-
84
-    /**
85
-     * built-in error code for \Illuminate\Auth\AuthenticationException
86
-     *
87
-     * @var int
88
-     */
89
-    protected const EX_VALIDATION_EXCEPTION_OFFSET = 15;
90
-
91
-    /**
92
-     * Returns base code mapping array
93
-     *
94
-     * @return array
95
-     */
96
-    protected static function getBaseMap(): array
97
-    {
98
-        $tpl = 'response-builder::builder.http_%d';
99
-
100
-        return [
101
-            /** @scrutinizer ignore-deprecated */
102
-            self::OK()                          => 'response-builder::builder.ok',
103
-            /** @scrutinizer ignore-deprecated */
104
-            self::NO_ERROR_MESSAGE()            => 'response-builder::builder.no_error_message',
105
-            /** @scrutinizer ignore-deprecated */
106
-            self::EX_HTTP_EXCEPTION()           => 'response-builder::builder.http_exception',
107
-            /** @scrutinizer ignore-deprecated */
108
-            self::EX_UNCAUGHT_EXCEPTION()       => 'response-builder::builder.uncaught_exception',
109
-            /** @scrutinizer ignore-deprecated */
110
-            self::EX_HTTP_NOT_FOUND()           => sprintf($tpl, HttpResponse::HTTP_NOT_FOUND),
111
-            /** @scrutinizer ignore-deprecated */
112
-            self::EX_HTTP_SERVICE_UNAVAILABLE() => sprintf($tpl, HttpResponse::HTTP_SERVICE_UNAVAILABLE),
113
-            /** @scrutinizer ignore-deprecated */
114
-            self::EX_AUTHENTICATION_EXCEPTION() => sprintf($tpl, HttpResponse::HTTP_UNAUTHORIZED),
115
-            /** @scrutinizer ignore-deprecated */
116
-            self::EX_VALIDATION_EXCEPTION()     => sprintf($tpl, HttpResponse::HTTP_UNPROCESSABLE_ENTITY),
117
-        ];
118
-    }
119
-
120
-    /**
121
-     * Returns API code for internal code OK
122
-     *
123
-     * @return int valid API code in current range
124
-     *
125
-     * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
126
-     */
127
-    public static function OK(): int
128
-    {
129
-        return static::getCodeForInternalOffset(static::OK_OFFSET);
130
-    }
131
-
132
-    /**
133
-     * Returns API code for internal code NO_ERROR_MESSAGE
134
-     *
135
-     * @return int valid API code in current range
136
-     */
137
-    public static function NO_ERROR_MESSAGE(): int
138
-    {
139
-        return static::getCodeForInternalOffset(static::NO_ERROR_MESSAGE_OFFSET);
140
-    }
141
-
142
-    /**
143
-     * Returns API code for internal code EX_HTTP_NOT_FOUND
144
-     *
145
-     * @return int valid API code in current range
146
-     *
147
-     * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
148
-     */
149
-    public static function EX_HTTP_NOT_FOUND(): int
150
-    {
151
-        return static::getCodeForInternalOffset(static::EX_HTTP_NOT_FOUND_OFFSET);
152
-    }
153
-
154
-    /**
155
-     * Returns API code for internal code EX_HTTP_EXCEPTION
156
-     *
157
-     * @return int valid API code in current range
158
-     *
159
-     * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
160
-     */
161
-    public static function EX_HTTP_EXCEPTION(): int
162
-    {
163
-        return static::getCodeForInternalOffset(static::EX_HTTP_EXCEPTION_OFFSET);
164
-    }
165
-
166
-    /**
167
-     * Returns API code for internal code EX_UNCAUGHT_EXCEPTION
168
-     *
169
-     * @return int valid API code in current range
170
-     *
171
-     * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
172
-     */
173
-    public static function EX_UNCAUGHT_EXCEPTION(): int
174
-    {
175
-        return static::getCodeForInternalOffset(static::EX_UNCAUGHT_EXCEPTION_OFFSET);
176
-    }
177
-
178
-    /**
179
-     * Returns API code for internal code EX_AUTHENTICATION_EXCEPTION
180
-     *
181
-     * @return int valid API code in current range
182
-     *
183
-     * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
184
-     */
185
-    public static function EX_AUTHENTICATION_EXCEPTION(): int
186
-    {
187
-        return static::getCodeForInternalOffset(static::EX_AUTHENTICATION_EXCEPTION_OFFSET);
188
-    }
189
-
190
-    /**
191
-     * Returns API code for internal code EX_VALIDATION_EXCEPTION
192
-     *
193
-     * @return int valid API code in current range
194
-     *
195
-     * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
196
-     */
197
-    public static function EX_VALIDATION_EXCEPTION(): int
198
-    {
199
-        return static::getCodeForInternalOffset(static::EX_VALIDATION_EXCEPTION_OFFSET);
200
-    }
201
-
202
-    /**
203
-     * Returns API code for internal code EX_HTTP_SERVICE_UNAVAILABLE
204
-     *
205
-     * @return int valid API code in current range
206
-     *
207
-     * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
208
-     */
209
-    public static function EX_HTTP_SERVICE_UNAVAILABLE(): int
210
-    {
211
-        return static::getCodeForInternalOffset(static::EX_HTTP_SERVICE_UNAVAILABLE_OFFSET);
212
-    }
24
+	use ApiCodesHelpers;
25
+
26
+	/**
27
+	 * protected code range - lowest code for reserved range.
28
+	 *
29
+	 * @var int
30
+	 */
31
+	public const RESERVED_MIN_API_CODE_OFFSET = 0;
32
+
33
+	/**
34
+	 * protected code range - highest code for reserved range
35
+	 *
36
+	 * @var int
37
+	 */
38
+	public const RESERVED_MAX_API_CODE_OFFSET = 19;
39
+
40
+	/**
41
+	 * built-in codes: OK
42
+	 *
43
+	 * @var int
44
+	 */
45
+	protected const OK_OFFSET = 0;
46
+	/**
47
+	 * built-in code for fallback message mapping
48
+	 *
49
+	 * @var int
50
+	 */
51
+	protected const NO_ERROR_MESSAGE_OFFSET = 1;
52
+	/**
53
+	 * built-in error code for HTTP_NOT_FOUND exception
54
+	 *
55
+	 * @var int
56
+	 */
57
+	protected const EX_HTTP_NOT_FOUND_OFFSET = 10;
58
+	/**
59
+	 * built-in error code for HTTP_SERVICE_UNAVAILABLE exception
60
+	 *
61
+	 * @var int
62
+	 */
63
+	protected const EX_HTTP_SERVICE_UNAVAILABLE_OFFSET = 11;
64
+	/**
65
+	 * built-in error code for HTTP_EXCEPTION
66
+	 *
67
+	 * @var int
68
+	 */
69
+	protected const EX_HTTP_EXCEPTION_OFFSET = 12;
70
+	/**
71
+	 * built-in error code for UNCAUGHT_EXCEPTION
72
+	 *
73
+	 * @var int
74
+	 */
75
+	protected const EX_UNCAUGHT_EXCEPTION_OFFSET = 13;
76
+
77
+	/**
78
+	 * built-in error code for \Illuminate\Auth\AuthenticationException
79
+	 *
80
+	 * @var int
81
+	 */
82
+	protected const EX_AUTHENTICATION_EXCEPTION_OFFSET = 14;
83
+
84
+	/**
85
+	 * built-in error code for \Illuminate\Auth\AuthenticationException
86
+	 *
87
+	 * @var int
88
+	 */
89
+	protected const EX_VALIDATION_EXCEPTION_OFFSET = 15;
90
+
91
+	/**
92
+	 * Returns base code mapping array
93
+	 *
94
+	 * @return array
95
+	 */
96
+	protected static function getBaseMap(): array
97
+	{
98
+		$tpl = 'response-builder::builder.http_%d';
99
+
100
+		return [
101
+			/** @scrutinizer ignore-deprecated */
102
+			self::OK()                          => 'response-builder::builder.ok',
103
+			/** @scrutinizer ignore-deprecated */
104
+			self::NO_ERROR_MESSAGE()            => 'response-builder::builder.no_error_message',
105
+			/** @scrutinizer ignore-deprecated */
106
+			self::EX_HTTP_EXCEPTION()           => 'response-builder::builder.http_exception',
107
+			/** @scrutinizer ignore-deprecated */
108
+			self::EX_UNCAUGHT_EXCEPTION()       => 'response-builder::builder.uncaught_exception',
109
+			/** @scrutinizer ignore-deprecated */
110
+			self::EX_HTTP_NOT_FOUND()           => sprintf($tpl, HttpResponse::HTTP_NOT_FOUND),
111
+			/** @scrutinizer ignore-deprecated */
112
+			self::EX_HTTP_SERVICE_UNAVAILABLE() => sprintf($tpl, HttpResponse::HTTP_SERVICE_UNAVAILABLE),
113
+			/** @scrutinizer ignore-deprecated */
114
+			self::EX_AUTHENTICATION_EXCEPTION() => sprintf($tpl, HttpResponse::HTTP_UNAUTHORIZED),
115
+			/** @scrutinizer ignore-deprecated */
116
+			self::EX_VALIDATION_EXCEPTION()     => sprintf($tpl, HttpResponse::HTTP_UNPROCESSABLE_ENTITY),
117
+		];
118
+	}
119
+
120
+	/**
121
+	 * Returns API code for internal code OK
122
+	 *
123
+	 * @return int valid API code in current range
124
+	 *
125
+	 * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
126
+	 */
127
+	public static function OK(): int
128
+	{
129
+		return static::getCodeForInternalOffset(static::OK_OFFSET);
130
+	}
131
+
132
+	/**
133
+	 * Returns API code for internal code NO_ERROR_MESSAGE
134
+	 *
135
+	 * @return int valid API code in current range
136
+	 */
137
+	public static function NO_ERROR_MESSAGE(): int
138
+	{
139
+		return static::getCodeForInternalOffset(static::NO_ERROR_MESSAGE_OFFSET);
140
+	}
141
+
142
+	/**
143
+	 * Returns API code for internal code EX_HTTP_NOT_FOUND
144
+	 *
145
+	 * @return int valid API code in current range
146
+	 *
147
+	 * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
148
+	 */
149
+	public static function EX_HTTP_NOT_FOUND(): int
150
+	{
151
+		return static::getCodeForInternalOffset(static::EX_HTTP_NOT_FOUND_OFFSET);
152
+	}
153
+
154
+	/**
155
+	 * Returns API code for internal code EX_HTTP_EXCEPTION
156
+	 *
157
+	 * @return int valid API code in current range
158
+	 *
159
+	 * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
160
+	 */
161
+	public static function EX_HTTP_EXCEPTION(): int
162
+	{
163
+		return static::getCodeForInternalOffset(static::EX_HTTP_EXCEPTION_OFFSET);
164
+	}
165
+
166
+	/**
167
+	 * Returns API code for internal code EX_UNCAUGHT_EXCEPTION
168
+	 *
169
+	 * @return int valid API code in current range
170
+	 *
171
+	 * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
172
+	 */
173
+	public static function EX_UNCAUGHT_EXCEPTION(): int
174
+	{
175
+		return static::getCodeForInternalOffset(static::EX_UNCAUGHT_EXCEPTION_OFFSET);
176
+	}
177
+
178
+	/**
179
+	 * Returns API code for internal code EX_AUTHENTICATION_EXCEPTION
180
+	 *
181
+	 * @return int valid API code in current range
182
+	 *
183
+	 * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
184
+	 */
185
+	public static function EX_AUTHENTICATION_EXCEPTION(): int
186
+	{
187
+		return static::getCodeForInternalOffset(static::EX_AUTHENTICATION_EXCEPTION_OFFSET);
188
+	}
189
+
190
+	/**
191
+	 * Returns API code for internal code EX_VALIDATION_EXCEPTION
192
+	 *
193
+	 * @return int valid API code in current range
194
+	 *
195
+	 * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
196
+	 */
197
+	public static function EX_VALIDATION_EXCEPTION(): int
198
+	{
199
+		return static::getCodeForInternalOffset(static::EX_VALIDATION_EXCEPTION_OFFSET);
200
+	}
201
+
202
+	/**
203
+	 * Returns API code for internal code EX_HTTP_SERVICE_UNAVAILABLE
204
+	 *
205
+	 * @return int valid API code in current range
206
+	 *
207
+	 * @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
208
+	 */
209
+	public static function EX_HTTP_SERVICE_UNAVAILABLE(): int
210
+	{
211
+		return static::getCodeForInternalOffset(static::EX_HTTP_SERVICE_UNAVAILABLE_OFFSET);
212
+	}
213 213
 
214 214
 }
Please login to merge, or discard this patch.