Skip to content

Commit

Permalink
Merge pull request #131 from MarcinOrlowski/dev
Browse files Browse the repository at this point in the history
Release v7.0.1
  • Loading branch information
MarcinOrlowski committed Nov 26, 2019
2 parents bb6c145 + 1f2c5eb commit 7b9d4fd
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 77 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ See [compatibility docs](docs/compatibility.md) for details about backward compa

## CHANGE LOG ##

* v7.0.1 (2019-11-25)
* Disabled Scrutinizer's "false positive" in Builder class.
* Added more tests to improve overall coverage.
* Updated PHPDocs

* v7.0.0 (2019-11-22)
* **BACKWARD INCOMPATIBLE CHANGES** ([more info](docs/compatibility.md))
* New, flexible API based on `Builder` pattern (see [docs](docs/compatibility.md) for details).
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "marcin-orlowski/laravel-api-response-builder",
"description": "Helps building nice, normalized and easy to consume Laravel REST API.",
"homepage": "https://github.com/MarcinOrlowski/laravel-api-response-builder",
"version": "7.0.0",
"version": "7.0.1",
"keywords": [
"laravel",
"json",
Expand Down
2 changes: 1 addition & 1 deletion docs/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
## Table of contents ##

* [Response structure](#response-structure)
* [Usage examples](#examples.md)
* [Usage examples](examples.md)
* [Return Codes and Code Ranges](#return-codes)
* [Exposed Methods](#exposed-methods)
* [Data Conversion](#data-conversion)
Expand Down
22 changes: 18 additions & 4 deletions src/BaseApiCodes.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,21 @@ protected static function getBaseMap(): array
$tpl = 'response-builder::builder.http_%d';

return [
/** @scrutinizer ignore-deprecated */
self::OK() => 'response-builder::builder.ok',
/** @scrutinizer ignore-deprecated */
self::NO_ERROR_MESSAGE() => 'response-builder::builder.no_error_message',
/** @scrutinizer ignore-deprecated */
self::EX_HTTP_EXCEPTION() => 'response-builder::builder.http_exception',
/** @scrutinizer ignore-deprecated */
self::EX_UNCAUGHT_EXCEPTION() => 'response-builder::builder.uncaught_exception',
/** @scrutinizer ignore-deprecated */
self::EX_HTTP_NOT_FOUND() => sprintf($tpl, HttpResponse::HTTP_NOT_FOUND),
/** @scrutinizer ignore-deprecated */
self::EX_HTTP_SERVICE_UNAVAILABLE() => sprintf($tpl, HttpResponse::HTTP_SERVICE_UNAVAILABLE),
/** @scrutinizer ignore-deprecated */
self::EX_AUTHENTICATION_EXCEPTION() => sprintf($tpl, HttpResponse::HTTP_UNAUTHORIZED),
/** @scrutinizer ignore-deprecated */
self::EX_VALIDATION_EXCEPTION() => sprintf($tpl, HttpResponse::HTTP_UNPROCESSABLE_ENTITY),
];
}
Expand All @@ -113,6 +121,8 @@ protected static function getBaseMap(): array
* Returns API code for internal code OK
*
* @return int valid API code in current range
*
* @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
*/
public static function OK(): int
{
Expand All @@ -134,7 +144,7 @@ public static function NO_ERROR_MESSAGE(): int
*
* @return int valid API code in current range
*
* @deprecated Configure Exception Handler to use your own API code.
* @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
*/
public static function EX_HTTP_NOT_FOUND(): int
{
Expand All @@ -145,6 +155,8 @@ public static function EX_HTTP_NOT_FOUND(): int
* Returns API code for internal code EX_HTTP_EXCEPTION
*
* @return int valid API code in current range
*
* @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
*/
public static function EX_HTTP_EXCEPTION(): int
{
Expand All @@ -155,6 +167,8 @@ public static function EX_HTTP_EXCEPTION(): int
* Returns API code for internal code EX_UNCAUGHT_EXCEPTION
*
* @return int valid API code in current range
*
* @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
*/
public static function EX_UNCAUGHT_EXCEPTION(): int
{
Expand All @@ -166,7 +180,7 @@ public static function EX_UNCAUGHT_EXCEPTION(): int
*
* @return int valid API code in current range
*
* @deprecated Configure Exception Handler to use your own API code.
* @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
*/
public static function EX_AUTHENTICATION_EXCEPTION(): int
{
Expand All @@ -178,7 +192,7 @@ public static function EX_AUTHENTICATION_EXCEPTION(): int
*
* @return int valid API code in current range
*
* @deprecated Configure Exception Handler to use your own API code.
* @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
*/
public static function EX_VALIDATION_EXCEPTION(): int
{
Expand All @@ -190,7 +204,7 @@ public static function EX_VALIDATION_EXCEPTION(): int
*
* @return int valid API code in current range
*
* @deprecated Configure Exception Handler to use your own API code.
* @deprecated Configure Exception Handler to use your own API code. This method will be removed in v8.
*/
public static function EX_HTTP_SERVICE_UNAVAILABLE(): int
{
Expand Down
28 changes: 0 additions & 28 deletions src/Builder.php

This file was deleted.

72 changes: 38 additions & 34 deletions src/ExceptionHandlerHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,68 +41,68 @@ public static function render(/** @scrutinizer ignore-unused */ $request, Except
$cfg = static::getExceptionHandlerConfig()['map'];

if ($ex instanceof HttpException) {
// Check if we have any exception configuration for this particular Http status code.
// Check if we have any exception configuration for this particular HTTP status code.
// This confing entry is guaranted to exist (at least 'default'). Enforced by tests.
$http_code = $ex->getStatusCode();
$ex_cfg = $cfg[ HttpException::class ][ $http_code ] ?? null;
$ex_cfg = $ex_cfg ?? $cfg[ HttpException::class ]['default'];
$result = self::processException($ex, $ex_cfg, $http_code);
$result = self::processException($ex, /** @scrutinizer ignore-type */ $ex_cfg, $http_code);
} elseif ($ex instanceof ValidationException) {
// This entry is guaranted to exist. Enforced by tests.
$http_code = HttpResponse::HTTP_UNPROCESSABLE_ENTITY;
$ex_cfg = $cfg[ HttpException::class ][ $http_code ];
$result = self::processException($ex, $ex_cfg, $http_code);
$result = self::processException($ex, $cfg[ HttpException::class ][ $http_code ], $http_code);
}

if ($result === null) {
// This entry is guaranted to exist. Enforced by tests.
$http_code = HttpResponse::HTTP_INTERNAL_SERVER_ERROR;
$ex_cfg = $cfg['default'];
$result = self::processException($ex, $ex_cfg, $http_code);
$result = self::processException($ex, $cfg['default'], HttpResponse::HTTP_INTERNAL_SERVER_ERROR);
}

return $result;
}

protected static function processException(\Exception $ex, array $ex_cfg, int $http_code)
/**
* Handles given exception and produces valid HTTP response object.
*
* @param \Exception $ex Exception to be handled.
* @param array $ex_cfg ExceptionHandler's config excerpt related to $ex exception type.
* @param int $fallback_http_code HTTP code to be assigned to produced $ex related response in
* case configuration array lacks own `http_code` value.
*
* @return \Symfony\Component\HttpFoundation\Response
*/
protected static function processException(\Exception $ex, array $ex_cfg, int $fallback_http_code)
{
$api_code = $ex_cfg['api_code'];
$http_code = $ex_cfg['http_code'] ?? $http_code;
$http_code = $ex_cfg['http_code'] ?? $fallback_http_code;
$msg_key = $ex_cfg['msg_key'] ?? null;
$msg_enforce = $ex_cfg['msg_enforce'] ?? false;

// No message key, let's get exception message and if there's nothing useful, fallback to built-in one.
$error_message = $ex->getMessage();
$msg = $ex->getMessage();
$placeholders = [
'api_code' => $api_code,
'message' => ($error_message !== '') ? $error_message : '???',
'message' => ($msg !== '') ? $msg : '???',
];

// shall we enforce error message?
if ($msg_enforce) {
// yes, please.
if ($msg_key === null) {
// there's no msg_key configured for this exact code, so let's obtain our default message
$error_message = ($msg_key === null) ? static::getErrorMessageForException($ex, $http_code, $placeholders) : Lang::get($msg_key, $placeholders);
$msg = ($msg_key === null) ? static::getErrorMessageForException($ex, $http_code, $placeholders)
: Lang::get($msg_key, $placeholders);
}
} else {
// nothing enforced, handling pipeline: ex_message -> user_defined msg -> http_ex -> default
if ($error_message === '') {
$error_message = ($msg_key === null) ? static::getErrorMessageForException($ex, $http_code, $placeholders) : Lang::get($msg_key, $placeholders);
// nothing enforced, handling pipeline: ex_message -> user_defined_msg -> http_ex -> default
if ($msg === '') {
$msg = ($msg_key === null) ? static::getErrorMessageForException($ex, $http_code, $placeholders)
: Lang::get($msg_key, $placeholders);
}
}

// Lets' try to build the error response with what we have now
$result = static::error($ex, $api_code, $http_code, $error_message);

if ($result === null) {
$ex_cfg = $cfg[ HttpException::class ][ $http_code ];
$api_code = $ex_cfg['api_code'] ?? BaseApiCodes::EX_VALIDATION_EXCEPTION();
$http_code = $ex_cfg['http_code'] ?? $http_code;
$result = static::error($ex, $api_code, $http_code, $error_message);
}

return $result;
return static::error($ex, $api_code, $http_code, $msg);
}

/**
Expand All @@ -124,7 +124,8 @@ protected static function getErrorMessageForException(\Exception $ex, int $http_
} else {
// Still got nothing? Fall back to built-in generic message for this type of exception.
$key = BaseApiCodes::getCodeMessageKey(($ex instanceof HttpException)
? BaseApiCodes::EX_HTTP_EXCEPTION() : BaseApiCodes::NO_ERROR_MESSAGE());
? /** @scrutinizer ignore-deprecated */ BaseApiCodes::EX_HTTP_EXCEPTION()
: /** @scrutinizer ignore-deprecated */ BaseApiCodes::NO_ERROR_MESSAGE());
$error_message = Lang::get($key, $placeholders);
}

Expand Down Expand Up @@ -206,29 +207,33 @@ protected static function error(Exception $ex,
->build();
}

protected
static function getExceptionHandlerDefaultConfig(): array
/**
* Returns default (built-in) exception handler config array.
*
* @return array
*/
protected static function getExceptionHandlerDefaultConfig(): array
{
return [
'map' => [
HttpException::class => [
// used by unauthenticated() to obtain api and http code for the exception
HttpResponse::HTTP_UNAUTHORIZED => [
'api_code' => BaseApiCodes::EX_AUTHENTICATION_EXCEPTION(),
'api_code' => /** @scrutinizer ignore-deprecated */ BaseApiCodes::EX_AUTHENTICATION_EXCEPTION(),
],
// Required by ValidationException handler
HttpResponse::HTTP_UNPROCESSABLE_ENTITY => [
'api_code' => BaseApiCodes::EX_VALIDATION_EXCEPTION(),
'api_code' => /** @scrutinizer ignore-deprecated */ BaseApiCodes::EX_VALIDATION_EXCEPTION(),
],
// default handler is mandatory. `default` entry MUST have both `api_code` and `http_code` set.
'default' => [
'api_code' => BaseApiCodes::EX_HTTP_EXCEPTION(),
'api_code' => /** @scrutinizer ignore-deprecated */ BaseApiCodes::EX_HTTP_EXCEPTION(),
'http_code' => HttpResponse::HTTP_BAD_REQUEST,
],
],
// default handler is mandatory. `default` entry MUST have both `api_code` and `http_code` set.
'default' => [
'api_code' => BaseApiCodes::EX_UNCAUGHT_EXCEPTION(),
'api_code' => /** @scrutinizer ignore-deprecated */ BaseApiCodes::EX_UNCAUGHT_EXCEPTION(),
'http_code' => HttpResponse::HTTP_INTERNAL_SERVER_ERROR,
],
],
Expand All @@ -240,8 +245,7 @@ static function getExceptionHandlerDefaultConfig(): array
*
* @return array
*/
protected
static function getExceptionHandlerConfig(): array
protected static function getExceptionHandlerConfig(): array
{
return Util::mergeConfig(static::getExceptionHandlerDefaultConfig(),
\Config::get(ResponseBuilder::CONF_KEY_EXCEPTION_HANDLER, []));
Expand Down

0 comments on commit 7b9d4fd

Please sign in to comment.