From 55914fb56b364abfc67b9910465660e1cf579a59 Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Mon, 19 Nov 2018 21:19:56 -0500 Subject: [PATCH 01/14] Update `status` to string to conform to JSONAPI specifactions --- src/AuthenticationHandler.php | 2 +- src/AuthorizationHandler.php | 2 +- src/BadRequestHttpHandler.php | 2 +- src/CieloRequestHandler.php | 2 +- src/ClientHandler.php | 2 +- src/JsonHandler.php | 2 +- src/MissingScopeHandler.php | 2 +- src/ModelNotFoundHandler.php | 2 +- src/NotFoundHttpHandler.php | 2 +- src/OAuthServerHandler.php | 2 +- src/ValidationHandler.php | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/AuthenticationHandler.php b/src/AuthenticationHandler.php index d409802..a253995 100644 --- a/src/AuthenticationHandler.php +++ b/src/AuthenticationHandler.php @@ -9,7 +9,7 @@ trait AuthenticationHandler public function authenticationException(AuthenticationException $exception) { $error = [[ - 'status' => 401, + 'status' => '401', 'code' => $this->getCode('authentication'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => $exception->getMessage(), diff --git a/src/AuthorizationHandler.php b/src/AuthorizationHandler.php index b323d14..1710e09 100644 --- a/src/AuthorizationHandler.php +++ b/src/AuthorizationHandler.php @@ -9,7 +9,7 @@ trait AuthorizationHandler public function authorizationException(AuthorizationException $exception) { $error = [[ - 'status' => 403, + 'status' => '403', 'code' => $this->getCode('authorization'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => __('exception::exceptions.authorization.title'), diff --git a/src/BadRequestHttpHandler.php b/src/BadRequestHttpHandler.php index 122421a..7d653af 100644 --- a/src/BadRequestHttpHandler.php +++ b/src/BadRequestHttpHandler.php @@ -11,7 +11,7 @@ public function badRequestHttpException(BadRequestHttpException $exception) $statusCode = $exception->getStatusCode(); $error = [[ - 'status' => $statusCode, + 'status' => (string)$statusCode, 'code' => $this->getCode('bad_request'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => 'bad_request', diff --git a/src/CieloRequestHandler.php b/src/CieloRequestHandler.php index 1f8d75d..f333397 100644 --- a/src/CieloRequestHandler.php +++ b/src/CieloRequestHandler.php @@ -13,7 +13,7 @@ public function cieloRequestException(CieloRequestException $e) do { $cieloError = $e->getCieloError(); $error = [ - 'status' => $e->getCode(), + 'status' => (string)$e->getCode(), 'code' => $this->getCode('cielo').$cieloError->getCode(), 'source' => ['pointer' => $e->getFile().':'.$e->getLine()], 'title' => $e->getMessage(), diff --git a/src/ClientHandler.php b/src/ClientHandler.php index 5bbf5b3..3e8fc8a 100644 --- a/src/ClientHandler.php +++ b/src/ClientHandler.php @@ -49,7 +49,7 @@ public function clientException($exception) } $error = [[ - 'status' => $statusCode, + 'status' => (string)$statusCode, 'code' => $code, 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => $title, diff --git a/src/JsonHandler.php b/src/JsonHandler.php index 873bc08..9a49d42 100644 --- a/src/JsonHandler.php +++ b/src/JsonHandler.php @@ -43,7 +43,7 @@ trait JsonHandler public function setDefaultResponse() { $error = [[ - 'status' => $this->getStatusCode(), + 'status' => (string)$this->getStatusCode(), 'code' => $this->getCode(), 'source' => ['pointer' => $this->getDescription()], 'title' => strtolower(class_basename($this->exception)), diff --git a/src/MissingScopeHandler.php b/src/MissingScopeHandler.php index d1331f9..7ef2d3f 100644 --- a/src/MissingScopeHandler.php +++ b/src/MissingScopeHandler.php @@ -9,7 +9,7 @@ trait MissingScopeHandler public function missingScopeException(MissingScopeException $exception) { $error = [[ - 'status' => 403, + 'status' => '403', 'code' => $this->getCode('missing_scope'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => 'missing_scope', diff --git a/src/ModelNotFoundHandler.php b/src/ModelNotFoundHandler.php index 32bcd54..e698f0a 100644 --- a/src/ModelNotFoundHandler.php +++ b/src/ModelNotFoundHandler.php @@ -18,7 +18,7 @@ public function modelNotFoundException(ModelNotFoundException $exception) $ids = implode($exception->getIds(), ','); $error = [[ - 'status' => 404, + 'status' => '404', 'code' => $this->getCode('model_not_found'), 'source' => ['pointer' => 'data/id'], 'title' => $exception->getMessage(), diff --git a/src/NotFoundHttpHandler.php b/src/NotFoundHttpHandler.php index f3a9037..f720495 100644 --- a/src/NotFoundHttpHandler.php +++ b/src/NotFoundHttpHandler.php @@ -15,7 +15,7 @@ public function notFoundHttpException(NotFoundHttpException $exception) { $statuCode = $exception->getStatusCode(); $error = [[ - 'status' => $statuCode, + 'status' => (string)$statuCode, 'code' => $this->getCode('not_found_http'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => $this->getDescription($exception), diff --git a/src/OAuthServerHandler.php b/src/OAuthServerHandler.php index 7ea7ad6..11b66e1 100644 --- a/src/OAuthServerHandler.php +++ b/src/OAuthServerHandler.php @@ -11,7 +11,7 @@ public function oAuthServerException(OAuthServerException $exception) $statusCode = $exception->getHttpStatusCode(); $error = [[ - 'status' => $statusCode, + 'status' => (string)$statusCode, 'code' => $this->getCode('not_found_http'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => $exception->getErrorType(), diff --git a/src/ValidationHandler.php b/src/ValidationHandler.php index b273f79..56c5f7e 100644 --- a/src/ValidationHandler.php +++ b/src/ValidationHandler.php @@ -39,7 +39,7 @@ public function jsonApiFormatErrorMessages(ValidationException $exception) foreach ($messages as $key => $message) { $attributes = $this->getValidationAttributes($validationFails, $key, $field); $error = [ - 'status' => 422, + 'status' => '422', 'code' => $attributes['code'], 'source' => ['parameter' => $field], 'title' => $attributes['title'], From c329a3a6b3f880549e4b5982973086882875675c Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Mon, 19 Nov 2018 21:23:51 -0500 Subject: [PATCH 02/14] Update `code` to string to conform to JSONAPI specifactions --- src/AuthenticationHandler.php | 2 +- src/AuthorizationHandler.php | 2 +- src/BadRequestHttpHandler.php | 2 +- src/CieloRequestHandler.php | 2 +- src/ClientHandler.php | 2 +- src/JsonHandler.php | 2 +- src/MissingScopeHandler.php | 2 +- src/ModelNotFoundHandler.php | 2 +- src/NotFoundHttpHandler.php | 2 +- src/OAuthServerHandler.php | 2 +- src/ValidationHandler.php | 4 ++-- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/AuthenticationHandler.php b/src/AuthenticationHandler.php index a253995..0cf82e3 100644 --- a/src/AuthenticationHandler.php +++ b/src/AuthenticationHandler.php @@ -10,7 +10,7 @@ public function authenticationException(AuthenticationException $exception) { $error = [[ 'status' => '401', - 'code' => $this->getCode('authentication'), + 'code' => (string)$this->getCode('authentication'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => $exception->getMessage(), 'detail' => __('exception::exceptions.authentication.detail'), diff --git a/src/AuthorizationHandler.php b/src/AuthorizationHandler.php index 1710e09..a71d6f8 100644 --- a/src/AuthorizationHandler.php +++ b/src/AuthorizationHandler.php @@ -10,7 +10,7 @@ public function authorizationException(AuthorizationException $exception) { $error = [[ 'status' => '403', - 'code' => $this->getCode('authorization'), + 'code' => (string)$this->getCode('authorization'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => __('exception::exceptions.authorization.title'), 'detail' => $exception->getMessage(), diff --git a/src/BadRequestHttpHandler.php b/src/BadRequestHttpHandler.php index 7d653af..a848436 100644 --- a/src/BadRequestHttpHandler.php +++ b/src/BadRequestHttpHandler.php @@ -12,7 +12,7 @@ public function badRequestHttpException(BadRequestHttpException $exception) $error = [[ 'status' => (string)$statusCode, - 'code' => $this->getCode('bad_request'), + 'code' => (string)$this->getCode('bad_request'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => 'bad_request', 'detail' => $exception->getMessage(), diff --git a/src/CieloRequestHandler.php b/src/CieloRequestHandler.php index f333397..c8d0e8b 100644 --- a/src/CieloRequestHandler.php +++ b/src/CieloRequestHandler.php @@ -14,7 +14,7 @@ public function cieloRequestException(CieloRequestException $e) $cieloError = $e->getCieloError(); $error = [ 'status' => (string)$e->getCode(), - 'code' => $this->getCode('cielo').$cieloError->getCode(), + 'code' => (string)$this->getCode('cielo').$cieloError->getCode(), 'source' => ['pointer' => $e->getFile().':'.$e->getLine()], 'title' => $e->getMessage(), 'detail' => $cieloError->getMessage(), diff --git a/src/ClientHandler.php b/src/ClientHandler.php index 3e8fc8a..e2948c7 100644 --- a/src/ClientHandler.php +++ b/src/ClientHandler.php @@ -50,7 +50,7 @@ public function clientException($exception) $error = [[ 'status' => (string)$statusCode, - 'code' => $code, + 'code' => (string)$code, 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => $title, 'detail' => $detail, diff --git a/src/JsonHandler.php b/src/JsonHandler.php index 9a49d42..3710b0b 100644 --- a/src/JsonHandler.php +++ b/src/JsonHandler.php @@ -44,7 +44,7 @@ public function setDefaultResponse() { $error = [[ 'status' => (string)$this->getStatusCode(), - 'code' => $this->getCode(), + 'code' => (string)$this->getCode(), 'source' => ['pointer' => $this->getDescription()], 'title' => strtolower(class_basename($this->exception)), 'detail' => $this->getMessage(), diff --git a/src/MissingScopeHandler.php b/src/MissingScopeHandler.php index 7ef2d3f..00f4074 100644 --- a/src/MissingScopeHandler.php +++ b/src/MissingScopeHandler.php @@ -10,7 +10,7 @@ public function missingScopeException(MissingScopeException $exception) { $error = [[ 'status' => '403', - 'code' => $this->getCode('missing_scope'), + 'code' => (string)$this->getCode('missing_scope'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => 'missing_scope', 'detail' => $exception->getMessage(), diff --git a/src/ModelNotFoundHandler.php b/src/ModelNotFoundHandler.php index e698f0a..54ea171 100644 --- a/src/ModelNotFoundHandler.php +++ b/src/ModelNotFoundHandler.php @@ -19,7 +19,7 @@ public function modelNotFoundException(ModelNotFoundException $exception) $error = [[ 'status' => '404', - 'code' => $this->getCode('model_not_found'), + 'code' => (string)$this->getCode('model_not_found'), 'source' => ['pointer' => 'data/id'], 'title' => $exception->getMessage(), 'detail' => __('exception::exceptions.model_not_found.title', ['model' => $entity]), diff --git a/src/NotFoundHttpHandler.php b/src/NotFoundHttpHandler.php index f720495..6059a0d 100644 --- a/src/NotFoundHttpHandler.php +++ b/src/NotFoundHttpHandler.php @@ -16,7 +16,7 @@ public function notFoundHttpException(NotFoundHttpException $exception) $statuCode = $exception->getStatusCode(); $error = [[ 'status' => (string)$statuCode, - 'code' => $this->getCode('not_found_http'), + 'code' => (string)$this->getCode('not_found_http'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => $this->getDescription($exception), 'detail' => $this->getNotFoundMessage($exception), diff --git a/src/OAuthServerHandler.php b/src/OAuthServerHandler.php index 11b66e1..942aa96 100644 --- a/src/OAuthServerHandler.php +++ b/src/OAuthServerHandler.php @@ -12,7 +12,7 @@ public function oAuthServerException(OAuthServerException $exception) $error = [[ 'status' => (string)$statusCode, - 'code' => $this->getCode('not_found_http'), + 'code' => (string)$this->getCode('not_found_http'), 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], 'title' => $exception->getErrorType(), 'detail' => $exception->getMessage(), diff --git a/src/ValidationHandler.php b/src/ValidationHandler.php index 56c5f7e..78b535b 100644 --- a/src/ValidationHandler.php +++ b/src/ValidationHandler.php @@ -40,7 +40,7 @@ public function jsonApiFormatErrorMessages(ValidationException $exception) $attributes = $this->getValidationAttributes($validationFails, $key, $field); $error = [ 'status' => '422', - 'code' => $attributes['code'], + 'code' => (string)$attributes['code'], 'source' => ['parameter' => $field], 'title' => $attributes['title'], 'detail' => $message, @@ -55,7 +55,7 @@ public function jsonApiFormatErrorMessages(ValidationException $exception) public function getValidationAttributes(array $validationFails, $key, $field) { return [ - 'code' => $this->getValidationCode($validationFails, $key, $field), + 'code' => (string)$this->getValidationCode($validationFails, $key, $field), 'title' => $this->getValidationTitle($validationFails, $key, $field), ]; } From c31c1544063be23199df803cdc8057ba14acff2d Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Mon, 19 Nov 2018 21:33:52 -0500 Subject: [PATCH 03/14] Auto generate string validation codes --- src/ValidationHandler.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ValidationHandler.php b/src/ValidationHandler.php index 78b535b..cbcd221 100644 --- a/src/ValidationHandler.php +++ b/src/ValidationHandler.php @@ -38,9 +38,10 @@ public function jsonApiFormatErrorMessages(ValidationException $exception) foreach ($validationMessages as $field => $messages) { foreach ($messages as $key => $message) { $attributes = $this->getValidationAttributes($validationFails, $key, $field); + $path = str_replace('/', ':', request()->path()); $error = [ 'status' => '422', - 'code' => (string)$attributes['code'], + 'code' => "V:{$path}:{$field}:{$key}", 'source' => ['parameter' => $field], 'title' => $attributes['title'], 'detail' => $message, From aa148ba2ad531d8e77303dbe984ab51bace3d19f Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Mon, 19 Nov 2018 21:54:21 -0500 Subject: [PATCH 04/14] Remove Key from code in ValidationHandler --- src/ValidationHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ValidationHandler.php b/src/ValidationHandler.php index cbcd221..a125872 100644 --- a/src/ValidationHandler.php +++ b/src/ValidationHandler.php @@ -41,7 +41,7 @@ public function jsonApiFormatErrorMessages(ValidationException $exception) $path = str_replace('/', ':', request()->path()); $error = [ 'status' => '422', - 'code' => "V:{$path}:{$field}:{$key}", + 'code' => "V:{$path}:{$field}", 'source' => ['parameter' => $field], 'title' => $attributes['title'], 'detail' => $message, From b3d9b07750a8ae11df77f14803230c7e3c06881b Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Mon, 19 Nov 2018 21:55:58 -0500 Subject: [PATCH 05/14] Add extra colon between path & field in code response of ValidationHandler --- src/ValidationHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ValidationHandler.php b/src/ValidationHandler.php index a125872..2045537 100644 --- a/src/ValidationHandler.php +++ b/src/ValidationHandler.php @@ -41,7 +41,7 @@ public function jsonApiFormatErrorMessages(ValidationException $exception) $path = str_replace('/', ':', request()->path()); $error = [ 'status' => '422', - 'code' => "V:{$path}:{$field}", + 'code' => "V:{$path}::{$field}", 'source' => ['parameter' => $field], 'title' => $attributes['title'], 'detail' => $message, From 4a3a49923837b5c0ed26fb01c58e76211ef8d314 Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Mon, 26 Nov 2018 23:33:59 -0500 Subject: [PATCH 06/14] update pointer for NotFoundHttpHandler --- src/NotFoundHttpHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NotFoundHttpHandler.php b/src/NotFoundHttpHandler.php index 6059a0d..a98ba29 100644 --- a/src/NotFoundHttpHandler.php +++ b/src/NotFoundHttpHandler.php @@ -17,7 +17,7 @@ public function notFoundHttpException(NotFoundHttpException $exception) $error = [[ 'status' => (string)$statuCode, 'code' => (string)$this->getCode('not_found_http'), - 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], + 'source' => ['pointer' => request()->path()], 'title' => $this->getDescription($exception), 'detail' => $this->getNotFoundMessage($exception), ]]; From 55ca9bc24e708756dbfe140965b1d2a1bacd7fd7 Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Fri, 21 Dec 2018 18:26:12 -0500 Subject: [PATCH 07/14] Add backtrace to meta --- src/AuthenticationHandler.php | 32 ++- src/AuthorizationHandler.php | 86 ++++--- src/BadRequestHttpHandler.php | 35 +-- src/CieloRequestHandler.php | 31 --- src/ClientHandler.php | 81 ------- src/JsonHandler.php | 310 ++++++++++++------------ src/JsonHandlerServiceProvider.php | 36 +-- src/MissingScopeHandler.php | 32 ++- src/ModelNotFoundHandler.php | 128 +++++----- src/NotFoundHttpHandler.php | 72 +++--- src/OAuthServerHandler.php | 34 ++- src/Responses/JsonApiResponse.php | 76 +++--- src/ValidationHandler.php | 176 +++++++------- src/config/json-exception-handler.php | 100 ++++---- src/resources/lang/en/exceptions.php | 66 ++--- src/resources/lang/pt-br/exceptions.php | 66 ++--- 16 files changed, 660 insertions(+), 701 deletions(-) delete mode 100644 src/CieloRequestHandler.php delete mode 100644 src/ClientHandler.php diff --git a/src/AuthenticationHandler.php b/src/AuthenticationHandler.php index 0cf82e3..e57a6f4 100644 --- a/src/AuthenticationHandler.php +++ b/src/AuthenticationHandler.php @@ -6,17 +6,25 @@ trait AuthenticationHandler { - public function authenticationException(AuthenticationException $exception) - { - $error = [[ - 'status' => '401', - 'code' => (string)$this->getCode('authentication'), - 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], - 'title' => $exception->getMessage(), - 'detail' => __('exception::exceptions.authentication.detail'), - ]]; - - $this->jsonApiResponse->setStatus(401); - $this->jsonApiResponse->setErrors($error); + public function authenticationException(AuthenticationException $exception) + { + $meta = []; + if (config('json-exception-handler.show_details_in_meta')) { + $meta['__raw_error__'] = [ + 'message' => $exception->getMessage(), + 'backtrace' => explode("\n", $exception->getTraceAsString()), + ]; } + $error = [[ + 'status' => '401', + 'code' => (string) $this->getCode('authentication'), + 'source' => ['pointer' => $exception->getFile() . ':' . $exception->getLine()], + 'title' => $exception->getMessage(), + 'detail' => __('exception::exceptions.authentication.detail'), + 'meta' => $meta + ]]; + + $this->jsonApiResponse->setStatus(401); + $this->jsonApiResponse->setErrors($error); + } } diff --git a/src/AuthorizationHandler.php b/src/AuthorizationHandler.php index a71d6f8..c7f9ee8 100644 --- a/src/AuthorizationHandler.php +++ b/src/AuthorizationHandler.php @@ -6,46 +6,54 @@ trait AuthorizationHandler { - public function authorizationException(AuthorizationException $exception) - { - $error = [[ - 'status' => '403', - 'code' => (string)$this->getCode('authorization'), - 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], - 'title' => __('exception::exceptions.authorization.title'), - 'detail' => $exception->getMessage(), - ]]; - - $this->jsonApiResponse->setStatus(403); - $this->jsonApiResponse->setErrors($error); + public function authorizationException(AuthorizationException $exception) + { + $meta = []; + if (config('json-exception-handler.show_details_in_meta')) { + $meta['__raw_error__'] = [ + 'message' => $exception->getMessage(), + 'backtrace' => explode("\n", $exception->getTraceAsString()), + ]; } - - public function generateDescription($traces) - { - $action = ''; - foreach ($traces as $trace) { - if ($trace['function'] === 'authorize') { - $action = $this->extractAction($trace['args']); - break; - } - } + $error = [[ + 'status' => '403', + 'code' => (string) $this->getCode('authorization'), + 'source' => ['pointer' => $exception->getFile() . ':' . $exception->getLine()], + 'title' => __('exception::exceptions.authorization.title'), + 'detail' => $exception->getMessage(), + 'meta' => $meta + ]]; + + $this->jsonApiResponse->setStatus(403); + $this->jsonApiResponse->setErrors($error); + } + + public function generateDescription($traces) + { + $action = ''; + foreach ($traces as $trace) { + if ($trace['function'] === 'authorize') { + $action = $this->extractAction($trace['args']); + break; + } } - - public function extractAction($args) - { - $action = reset($args); - - $this->getWord($action); - } - - public function getWords($action) - { - $words = explode('.', $action); - if (! (count($words) > 1)) { - $words = explode('-', $action); - if (! (count($words) > 1)) { - $words = preg_split('/(?=[A-Z])/', $action); - } - } + } + + public function extractAction($args) + { + $action = reset($args); + + $this->getWord($action); + } + + public function getWords($action) + { + $words = explode('.', $action); + if (!(count($words) > 1)) { + $words = explode('-', $action); + if (!(count($words) > 1)) { + $words = preg_split('/(?=[A-Z])/', $action); + } } + } } diff --git a/src/BadRequestHttpHandler.php b/src/BadRequestHttpHandler.php index a848436..ee24000 100644 --- a/src/BadRequestHttpHandler.php +++ b/src/BadRequestHttpHandler.php @@ -6,19 +6,26 @@ trait BadRequestHttpHandler { - public function badRequestHttpException(BadRequestHttpException $exception) - { - $statusCode = $exception->getStatusCode(); - - $error = [[ - 'status' => (string)$statusCode, - 'code' => (string)$this->getCode('bad_request'), - 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], - 'title' => 'bad_request', - 'detail' => $exception->getMessage(), - ]]; - - $this->jsonApiResponse->setStatus($statusCode); - $this->jsonApiResponse->setErrors($error); + public function badRequestHttpException(BadRequestHttpException $exception) + { + $statusCode = $exception->getStatusCode(); + $meta = []; + if (config('json-exception-handler.show_details_in_meta')) { + $meta['__raw_error__'] = [ + 'message' => $exception->getMessage(), + 'backtrace' => explode("\n", $exception->getTraceAsString()), + ]; } + $error = [[ + 'status' => (string) $statusCode, + 'code' => (string) $this->getCode('bad_request'), + 'source' => ['pointer' => $exception->getFile() . ':' . $exception->getLine()], + 'title' => 'bad_request', + 'detail' => $exception->getMessage(), + 'meta' => $meta + ]]; + + $this->jsonApiResponse->setStatus($statusCode); + $this->jsonApiResponse->setErrors($error); + } } diff --git a/src/CieloRequestHandler.php b/src/CieloRequestHandler.php deleted file mode 100644 index c8d0e8b..0000000 --- a/src/CieloRequestHandler.php +++ /dev/null @@ -1,31 +0,0 @@ -getCode(); - do { - $cieloError = $e->getCieloError(); - $error = [ - 'status' => (string)$e->getCode(), - 'code' => (string)$this->getCode('cielo').$cieloError->getCode(), - 'source' => ['pointer' => $e->getFile().':'.$e->getLine()], - 'title' => $e->getMessage(), - 'detail' => $cieloError->getMessage(), - ]; - if (! in_array($error, $errors)) { - array_push($errors, $error); - } - $e = $e->getPrevious(); - } while (method_exists($e, 'getPrevious')); - - $this->jsonApiResponse->setStatus($code); - $this->jsonApiResponse->setErrors($errors); - } -} diff --git a/src/ClientHandler.php b/src/ClientHandler.php deleted file mode 100644 index e2948c7..0000000 --- a/src/ClientHandler.php +++ /dev/null @@ -1,81 +0,0 @@ -getMessage(); - $code = $this->getCode(); - - if ($exception instanceof ClientException) { - $requestHost = $exception->getRequest()->getUri()->getHost(); - $clientCausers = $this->clientExceptionCausers(); - - $response = $exception->getResponse(); - - if ($clientCausers->isPagarme($requestHost)) { - $code = config('json-exception-handler.codes.client.pagarme') ?? 'pagarme'; - $errors = json_decode($response->getBody())->errors; - - $firstErrorMessage = ''; - foreach ($errors as $error) { - $firstErrorMessage = $error->message; - break; - } - - $detailedError = $firstErrorMessage.' #'.$code; - } elseif ($clientCausers->isMailgun($requestHost)) { - $code = config('json-exception-handler.codes.client.mailgun') ?? 'mailgun'; - $detailedError = json_decode($response->getBody())->message.' #'.$code; - } else { - // Unknown error - $code = config('json-exception-handler.codes.client.default'); - } - - if (App::environment('production')) { - $detail = __('exception::exceptions.client.unavailable').' #'.$code; - } else { - // Return more details about error - $detail = $detailedError ?? $detail; - $statusCode = $response->getStatusCode(); - } - } - - $error = [[ - 'status' => (string)$statusCode, - 'code' => (string)$code, - 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], - 'title' => $title, - 'detail' => $detail, - ]]; - - $this->jsonApiResponse->setStatus($statusCode); - $this->jsonApiResponse->setErrors($error); - } - - public function clientExceptionCausers() - { - return new class() { - const PAGARME_HOST = 'api.pagar.me'; - - const MAILGUN_HOST = 'api.mailgun.net'; - - public function isPagarme($host) - { - return self::PAGARME_HOST == $host; - } - - public function isMailgun($host) - { - return self::MAILGUN_HOST == $host; - } - }; - } -} diff --git a/src/JsonHandler.php b/src/JsonHandler.php index 3710b0b..20a847f 100644 --- a/src/JsonHandler.php +++ b/src/JsonHandler.php @@ -7,162 +7,170 @@ trait JsonHandler { - use ValidationHandler, - ModelNotFoundHandler, - AuthorizationHandler, - NotFoundHttpHandler, - AuthenticationHandler, - OAuthServerHandler, - MissingScopeHandler, - BadRequestHttpHandler, - ClientHandler, - CieloRequestHandler; - - /** - * Config file name. - * @var string - */ - public $configFile = 'json-exception-handler'; - - /** - * JsonApiResponse instance used on another traits to set response. - * @var SMartins\JsonHandler\Responses\JsonApiResponse; - */ - public $jsonApiResponse; - - /** - * Receive exception instance to be used on methods. - * @var Exception - */ - private $exception; - - /** - * Set the default response on $response attribute. Get default value from - * methods. - */ - public function setDefaultResponse() - { - $error = [[ - 'status' => (string)$this->getStatusCode(), - 'code' => (string)$this->getCode(), - 'source' => ['pointer' => $this->getDescription()], - 'title' => strtolower(class_basename($this->exception)), - 'detail' => $this->getMessage(), - ]]; - - $this->jsonApiResponse->setStatus($this->getStatusCode()); - $this->jsonApiResponse->setErrors($error); + use ValidationHandler, + ModelNotFoundHandler, + AuthorizationHandler, + NotFoundHttpHandler, + AuthenticationHandler, + OAuthServerHandler, + MissingScopeHandler, + BadRequestHttpHandler, + ClientHandler, + CieloRequestHandler; + + /** + * Config file name. + * @var string + */ + public $configFile = 'json-exception-handler'; + + /** + * JsonApiResponse instance used on another traits to set response. + * @var SMartins\JsonHandler\Responses\JsonApiResponse; + */ + public $jsonApiResponse; + + /** + * Receive exception instance to be used on methods. + * @var Exception + */ + private $exception; + + /** + * Set the default response on $response attribute. Get default value from + * methods. + */ + public function setDefaultResponse() + { + $meta = []; + if (config($this->configFile . '.show_details_in_meta')) { + $meta['__raw_error__'] = [ + 'message' => $this->getMessage(), + 'backtrace' => explode("\n", $this->exception->getTraceAsString()), + ]; } - - /** - * Get default message from exception. - * - * @return string Exception message - */ - public function getMessage() - { - return $this->exception->getMessage(); - } - - /** - * Mount the description with exception class, line and file. - * - * @return string - */ - public function getDescription() - { - return class_basename($this->exception). - ' line '.$this->exception->getLine(). - ' in '.$this->exception->getFile(); - } - - /** - * Get default http code. Check if exception has getStatusCode() methods. - * If not get from config file. - * - * @return int - */ - public function getStatusCode() - { - if (method_exists($this->exception, 'getStatusCode')) { - $httpCode = $this->exception->getStatusCode(); - } else { - $httpCode = config($this->configFile.'.http_code'); - } - - return $httpCode; + $error = [[ + 'status' => (string) $this->getStatusCode(), + 'code' => (string) $this->getCode(), + 'source' => ['pointer' => $this->getDescription()], + 'title' => str_replace('Exception', '', class_basename($this->exception)), + 'detail' => $this->getMessage(), + 'meta' => $meta, + ]]; + + $this->jsonApiResponse->setStatus($this->getStatusCode()); + $this->jsonApiResponse->setErrors($error); + } + + /** + * Get default message from exception. + * + * @return string Exception message + */ + public function getMessage() + { + return $this->exception->getMessage(); + } + + /** + * Mount the description with exception class, line and file. + * + * @return string + */ + public function getDescription() + { + return class_basename($this->exception) . + ' line ' . $this->exception->getLine() . + ' in ' . $this->exception->getFile(); + } + + /** + * Get default http code. Check if exception has getStatusCode() methods. + * If not get from config file. + * + * @return int + */ + public function getStatusCode() + { + if (method_exists($this->exception, 'getStatusCode')) { + $httpCode = $this->exception->getStatusCode(); + } else { + $httpCode = config($this->configFile . '.http_code'); } - /** - * Get error code. If code is empty from config file based on type. - * - * @param string $type Code type from config file - * @return int - */ - public function getCode($type = 'default') - { - $code = $this->exception->getCode(); - if (empty($this->exception->getCode())) { - $code = config($this->configFile.'.codes.'.$type); - } - - return $code; + return $httpCode; + } + + /** + * Get error code. If code is empty from config file based on type. + * + * @param string $type Code type from config file + * @return int + */ + public function getCode($type = 'default') + { + $code = $this->exception->getCode(); + if (empty($this->exception->getCode())) { + $code = config($this->configFile . '.codes.' . $type); } - /** - * Handle the json response. Check if exception is treated. If true call - * the specific handler. If false set the default response to be returned. - * - * @param Exception $exception - * @return JsonResponse - */ - public function jsonResponse(Exception $exception) - { - $this->exception = $exception; - $this->jsonApiResponse = new JsonApiResponse; - - if ($this->exceptionIsTreated()) { - $this->callExceptionHandler(); - } else { - $this->setDefaultResponse(); - } - - return response()->json( - $this->jsonApiResponse->toArray(), - $this->jsonApiResponse->getStatus() - ); + return $code; + } + + /** + * Handle the json response. Check if exception is treated. If true call + * the specific handler. If false set the default response to be returned. + * + * @param Exception $exception + * @return JsonResponse + */ + public function jsonResponse(Exception $exception) + { + $this->exception = $exception; + $this->jsonApiResponse = new JsonApiResponse; + + if ($this->exceptionIsTreated()) { + $this->callExceptionHandler(); + } else { + $this->setDefaultResponse(); } - /** - * Check if method to treat exception exists. - * - * @param Exception $exception The exception to be checked - * @return bool If method is callable - */ - public function exceptionIsTreated() - { - return is_callable([$this, $this->methodName()]); - } - - /** - * Call the exception handler after of to check if the method exists. - * - * @param Exception $exception - * @return void Call the method - */ - public function callExceptionHandler() - { - $this->{$this->methodName()}($this->exception); - } - - /** - * The method name is the exception name with first letter in lower case. - * - * @param Exception $exception - * @return string The method name - */ - public function methodName() - { - return lcfirst(class_basename($this->exception)); - } + return response()->json( + $this->jsonApiResponse->toArray(), + $this->jsonApiResponse->getStatus() + ); + } + + /** + * Check if method to treat exception exists. + * + * @param Exception $exception The exception to be checked + * @return bool If method is callable + */ + public function exceptionIsTreated() + { + return is_callable([$this, $this->methodName()]); + } + + /** + * Call the exception handler after of to check if the method exists. + * + * @param Exception $exception + * @return void Call the method + */ + public function callExceptionHandler() + { + $this->{$this->methodName()}($this->exception); + } + + /** + * The method name is the exception name with first letter in lower case. + * + * @param Exception $exception + * @return string The method name + */ + public function methodName() + { + return lcfirst(class_basename($this->exception)); + } } diff --git a/src/JsonHandlerServiceProvider.php b/src/JsonHandlerServiceProvider.php index 7de8927..31b2f58 100644 --- a/src/JsonHandlerServiceProvider.php +++ b/src/JsonHandlerServiceProvider.php @@ -6,26 +6,26 @@ class JsonHandlerServiceProvider extends ServiceProvider { - public function boot() - { - $this->publishes([ - $this->configPath() => config_path('json-exception-handler.php'), - ]); + public function boot() + { + $this->publishes([ + $this->configPath() => config_path('json-exception-handler.php'), + ]); - $this->loadTranslationsFrom(__DIR__.'/resources/lang', 'exception'); + $this->loadTranslationsFrom(__DIR__ . '/resources/lang', 'exception'); - $this->publishes([ - __DIR__.'/resources/lang' => resource_path('lang/vendor/exception'), - ]); - } + $this->publishes([ + __DIR__ . '/resources/lang' => resource_path('lang/vendor/exception'), + ]); + } - public function register() - { - $this->mergeConfigFrom($this->configPath(), 'json-exception-handler'); - } + public function register() + { + $this->mergeConfigFrom($this->configPath(), 'json-exception-handler'); + } - public function configPath() - { - return __DIR__.'/config/json-exception-handler.php'; - } + public function configPath() + { + return __DIR__ . '/config/json-exception-handler.php'; + } } diff --git a/src/MissingScopeHandler.php b/src/MissingScopeHandler.php index 00f4074..84f202f 100644 --- a/src/MissingScopeHandler.php +++ b/src/MissingScopeHandler.php @@ -6,17 +6,25 @@ trait MissingScopeHandler { - public function missingScopeException(MissingScopeException $exception) - { - $error = [[ - 'status' => '403', - 'code' => (string)$this->getCode('missing_scope'), - 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], - 'title' => 'missing_scope', - 'detail' => $exception->getMessage(), - ]]; - - $this->jsonApiResponse->setStatus(403); - $this->jsonApiResponse->setErrors($error); + public function missingScopeException(MissingScopeException $exception) + { + $meta = []; + if (config('json-exception-handler.show_details_in_meta')) { + $meta['__raw_error__'] = [ + 'message' => $exception->getMessage(), + 'backtrace' => explode("\n", $exception->getTraceAsString()), + ]; } + $error = [[ + 'status' => '403', + 'code' => (string) $this->getCode('missing_scope'), + 'source' => ['pointer' => $exception->getFile() . ':' . $exception->getLine()], + 'title' => 'missing_scope', + 'detail' => $exception->getMessage(), + 'meta' => $meta, + ]]; + + $this->jsonApiResponse->setStatus(403); + $this->jsonApiResponse->setErrors($error); + } } diff --git a/src/ModelNotFoundHandler.php b/src/ModelNotFoundHandler.php index 54ea171..b975f2f 100644 --- a/src/ModelNotFoundHandler.php +++ b/src/ModelNotFoundHandler.php @@ -6,71 +6,83 @@ trait ModelNotFoundHandler { - /** - * Set the response if Exception is ModelNotFound. - * - * @param ModelNotFoundException $exception - */ - public function modelNotFoundException(ModelNotFoundException $exception) - { - $entity = $this->extractEntityName($exception->getModel()); - - $ids = implode($exception->getIds(), ','); - - $error = [[ - 'status' => '404', - 'code' => (string)$this->getCode('model_not_found'), - 'source' => ['pointer' => 'data/id'], - 'title' => $exception->getMessage(), - 'detail' => __('exception::exceptions.model_not_found.title', ['model' => $entity]), - ]]; - - $this->jsonApiResponse->setStatus(404); - $this->jsonApiResponse->setErrors($error); + /** + * Set the response if Exception is ModelNotFound. + * + * @param ModelNotFoundException $exception + */ + public function modelNotFoundException(ModelNotFoundException $exception) + { + $entity = $this->extractEntityName($exception->getModel()); + + $ids = implode($exception->getIds(), ','); + + $meta = [ + 'attribute' => 'id' + ]; + + if (config('json-exception-handler.show_details_in_meta')) { + $meta['__raw_error__'] = [ + 'message' => $exception->getMessage(), + 'backtrace' => explode("\n", $exception->getTraceAsString()), + ]; } - /** - * Get entitie name based on model path to mount the message. - * - * @param string $model - * @return string - */ - public function extractEntityName($model) - { - $classNames = (array) explode('\\', $model); + $error = [[ + 'status' => '404', + 'code' => (string) $this->getCode('model_not_found'), + 'source' => ['pointer' => 'data/id'], + 'title' => $exception->getMessage(), + 'detail' => __('exception::exceptions.model_not_found.title', ['model' => $entity]), + 'meta' => $meta + ]]; - $entityName = end($classNames); + $this->jsonApiResponse->setStatus(404); + $this->jsonApiResponse->setErrors($error); + } - if ($this->entityHasTranslation($entityName)) { - return __('exception::exceptions.models.'.$entityName); - } + /** + * Get entitie name based on model path to mount the message. + * + * @param string $model + * @return string + */ + public function extractEntityName($model) + { + $classNames = (array) explode('\\', $model); - return $entityName; - } + $entityName = end($classNames); - /** - * Check if entity returned on ModelNotFoundException has translation on - * exceptions file - * @param string $entityName The model name to check if has translation - * @return bool Has translation or not - */ - public function entityHasTranslation(string $entityName): bool - { - $hasKey = in_array($entityName, $this->translationModelKeys()); - - if ($hasKey) { - return ! empty($hasKey); - } - - return false; + if ($this->entityHasTranslation($entityName)) { + return __('exception::exceptions.models.' . $entityName); } - /** - * Get the models keys on exceptions lang file - * @return array An array with keys to translate - */ - private function translationModelKeys(): array - { - return array_keys(__('exception::exceptions.models')); + return $entityName; + } + + /** + * Check if entity returned on ModelNotFoundException has translation on + * exceptions file + * @param string $entityName The model name to check if has translation + * @return bool Has translation or not + */ + public function entityHasTranslation(string $entityName): bool + { + $hasKey = in_array($entityName, $this->translationModelKeys()); + + if ($hasKey) { + return !empty($hasKey); } + + return false; + } + + /** + * Get the models keys on exceptions lang file + * @return array An array with keys to translate + */ + private function translationModelKeys(): array + { + return array_keys(__('exception::exceptions.models')); + } } diff --git a/src/NotFoundHttpHandler.php b/src/NotFoundHttpHandler.php index a98ba29..15bcb41 100644 --- a/src/NotFoundHttpHandler.php +++ b/src/NotFoundHttpHandler.php @@ -6,40 +6,48 @@ trait NotFoundHttpHandler { - /** - * Set response parameters to NotFoundHttpException. - * - * @param NotFoundHttpException $exception - */ - public function notFoundHttpException(NotFoundHttpException $exception) - { - $statuCode = $exception->getStatusCode(); - $error = [[ - 'status' => (string)$statuCode, - 'code' => (string)$this->getCode('not_found_http'), - 'source' => ['pointer' => request()->path()], - 'title' => $this->getDescription($exception), - 'detail' => $this->getNotFoundMessage($exception), - ]]; - - $this->jsonApiResponse->setStatus($statuCode); - $this->jsonApiResponse->setErrors($error); + /** + * Set response parameters to NotFoundHttpException. + * + * @param NotFoundHttpException $exception + */ + public function notFoundHttpException(NotFoundHttpException $exception) + { + $statuCode = $exception->getStatusCode(); + $meta = []; + if (config('json-exception-handler.show_details_in_meta')) { + $meta['__raw_error__'] = [ + 'message' => $exception->getMessage(), + 'backtrace' => explode("\n", $exception->getTraceAsString()), + ]; } + $error = [[ + 'status' => (string) $statuCode, + 'code' => (string) $this->getCode('not_found_http'), + 'source' => ['pointer' => request()->path()], + 'title' => $this->getDescription($exception), + 'detail' => $this->getNotFoundMessage($exception), + 'meta' => $meta + ]]; - /** - * Get message based on file. If file is RouteCollection return specific - * message. - * - * @param NotFoundHttpException $exception - * @return string - */ - public function getNotFoundMessage(NotFoundHttpException $exception) - { - $message = ! empty($exception->getMessage()) ? $exception->getMessage() : class_basename($exception); - if (basename($exception->getFile()) === 'RouteCollection.php') { - $message = __('exception::exceptions.not_found_http.message'); - } + $this->jsonApiResponse->setStatus($statuCode); + $this->jsonApiResponse->setErrors($error); + } - return $message; + /** + * Get message based on file. If file is RouteCollection return specific + * message. + * + * @param NotFoundHttpException $exception + * @return string + */ + public function getNotFoundMessage(NotFoundHttpException $exception) + { + $message = !empty($exception->getMessage()) ? $exception->getMessage() : class_basename($exception); + if (basename($exception->getFile()) === 'RouteCollection.php') { + $message = __('exception::exceptions.not_found_http.message'); } + + return $message; + } } diff --git a/src/OAuthServerHandler.php b/src/OAuthServerHandler.php index 942aa96..2a03b39 100644 --- a/src/OAuthServerHandler.php +++ b/src/OAuthServerHandler.php @@ -6,19 +6,27 @@ trait OAuthServerHandler { - public function oAuthServerException(OAuthServerException $exception) - { - $statusCode = $exception->getHttpStatusCode(); + public function oAuthServerException(OAuthServerException $exception) + { + $statusCode = $exception->getHttpStatusCode(); + $meta = []; + if (config('json-exception-handler.show_details_in_meta')) { + $meta['__raw_error__'] = [ + 'message' => $exception->getMessage(), + 'backtrace' => explode("\n", $exception->getTraceAsString()), + ]; + } - $error = [[ - 'status' => (string)$statusCode, - 'code' => (string)$this->getCode('not_found_http'), - 'source' => ['pointer' => $exception->getFile().':'.$exception->getLine()], - 'title' => $exception->getErrorType(), - 'detail' => $exception->getMessage(), - ]]; + $error = [[ + 'status' => (string) $statusCode, + 'code' => (string) $this->getCode('not_found_http'), + 'source' => ['pointer' => $exception->getFile() . ':' . $exception->getLine()], + 'title' => $exception->getErrorType(), + 'detail' => $exception->getMessage(), + 'meta' => $meta + ]]; - $this->jsonApiResponse->setStatus($statusCode); - $this->jsonApiResponse->setErrors($error); - } + $this->jsonApiResponse->setStatus($statusCode); + $this->jsonApiResponse->setErrors($error); + } } diff --git a/src/Responses/JsonApiResponse.php b/src/Responses/JsonApiResponse.php index 63ce8e4..a6d0b0d 100644 --- a/src/Responses/JsonApiResponse.php +++ b/src/Responses/JsonApiResponse.php @@ -4,42 +4,42 @@ class JsonApiResponse { - protected $status; - - protected $errors; - - public function getStatus() - { - return $this->status; - } - - public function status() - { - return $this->getStatus(); - } - - public function getErrors() - { - return $this->errors; - } - - public function errors() - { - return $this->getErrors(); - } - - public function setStatus($status) - { - $this->status = $status; - } - - public function setErrors($errors) - { - $this->errors = $errors; - } - - public function toArray() - { - return ['errors' => $this->errors()]; - } + protected $status; + + protected $errors; + + public function getStatus() + { + return $this->status; + } + + public function status() + { + return $this->getStatus(); + } + + public function getErrors() + { + return $this->errors; + } + + public function errors() + { + return $this->getErrors(); + } + + public function setStatus($status) + { + $this->status = $status; + } + + public function setErrors($errors) + { + $this->errors = $errors; + } + + public function toArray() + { + return ['errors' => $this->errors()]; + } } diff --git a/src/ValidationHandler.php b/src/ValidationHandler.php index 2045537..be8b825 100644 --- a/src/ValidationHandler.php +++ b/src/ValidationHandler.php @@ -6,102 +6,106 @@ trait ValidationHandler { - /** - * Assign to response attribute the value to ValidationException. - * - * @param ValidationException $exception - */ - public function validationException(ValidationException $exception) - { - $this->jsonApiResponse->setStatus(422); - $this->jsonApiResponse->setErrors($this->jsonApiFormatErrorMessages($exception)); - } - - /** - * Get formatted errors on standard code, field, message to each field with - * error. - * - * @param ValidationException $exception - * @return array - */ - public function formattedErrors(ValidationException $exception) - { - return $this->jsonApiFormatErrorMessages($exception); - } + /** + * Assign to response attribute the value to ValidationException. + * + * @param ValidationException $exception + */ + public function validationException(ValidationException $exception) + { + $this->jsonApiResponse->setStatus(422); + $this->jsonApiResponse->setErrors($this->jsonApiFormatErrorMessages($exception)); + } - public function jsonApiFormatErrorMessages(ValidationException $exception) - { - $validationMessages = $this->getTreatedMessages($exception); - $validationFails = $this->getTreatedFails($exception); + /** + * Get formatted errors on standard code, field, message to each field with + * error. + * + * @param ValidationException $exception + * @return array + */ + public function formattedErrors(ValidationException $exception) + { + return $this->jsonApiFormatErrorMessages($exception); + } - $errors = []; - foreach ($validationMessages as $field => $messages) { - foreach ($messages as $key => $message) { - $attributes = $this->getValidationAttributes($validationFails, $key, $field); - $path = str_replace('/', ':', request()->path()); - $error = [ - 'status' => '422', - 'code' => "V:{$path}::{$field}", - 'source' => ['parameter' => $field], - 'title' => $attributes['title'], - 'detail' => $message, - ]; - array_push($errors, $error); - } - } + public function jsonApiFormatErrorMessages(ValidationException $exception) + { + $validationMessages = $this->getTreatedMessages($exception); + $validationFails = $this->getTreatedFails($exception); - return $errors; - } - - public function getValidationAttributes(array $validationFails, $key, $field) - { - return [ - 'code' => (string)$this->getValidationCode($validationFails, $key, $field), - 'title' => $this->getValidationTitle($validationFails, $key, $field), + $errors = []; + foreach ($validationMessages as $field => $messages) { + foreach ($messages as $key => $message) { + $attributes = $this->getValidationAttributes($validationFails, $key, $field); + $path = str_replace('/', ':', request()->path()); + $error = [ + 'status' => '422', + 'code' => "V:{$path}::{$field}", + 'source' => ['parameter' => $field], + 'title' => $attributes['title'], + 'detail' => $message, + 'meta' => [ + 'attribute' => $field, + 'message' => $message + ] ]; + array_push($errors, $error); + } } - public function getValidationTitle(array $validationFails, $key, $field) - { - return __('exception::exceptions.validation.title', [ - 'fails' => array_keys($validationFails[$field])[$key], - 'field' => $field, - ]); - } + return $errors; + } - public function getValidationCode(array $validationFails, $key, $field) - { - $rule = strtolower(array_keys($validationFails[$field])[$key]); + public function getValidationAttributes(array $validationFails, $key, $field) + { + return [ + 'code' => (string) $this->getValidationCode($validationFails, $key, $field), + 'title' => $this->getValidationTitle($validationFails, $key, $field), + ]; + } - return config($this->configFile.'.codes.validation_fields.'.$field.'.'.$rule); - } + public function getValidationTitle(array $validationFails, $key, $field) + { + return __('exception::exceptions.validation.title', [ + 'fails' => array_keys($validationFails[$field])[$key], + 'field' => $field, + ]); + } - /** - * Get message based on exception type. If exception is generated by - * $this->validate() from default Controller methods the exception has the - * response object. If exception is generated by Validator::make() the - * messages are getted different. - * - * @param Exception $exception - * @return array - */ - public function getTreatedMessages($exception) - { - return $this->getMessagesFromValidator($exception); - } + public function getValidationCode(array $validationFails, $key, $field) + { + $rule = strtolower(array_keys($validationFails[$field])[$key]); - public function getMessagesFromValidator($exception) - { - return $exception->validator->messages()->messages(); - } + return config($this->configFile . '.codes.validation_fields.' . $field . '.' . $rule); + } - public function getTreatedFails($exception) - { - return $this->getFailsFromValidator($exception); - } + /** + * Get message based on exception type. If exception is generated by + * $this->validate() from default Controller methods the exception has the + * response object. If exception is generated by Validator::make() the + * messages are getted different. + * + * @param Exception $exception + * @return array + */ + public function getTreatedMessages($exception) + { + return $this->getMessagesFromValidator($exception); + } - public function getFailsFromValidator($exception) - { - return $exception->validator->failed(); - } + public function getMessagesFromValidator($exception) + { + return $exception->validator->messages()->messages(); + } + + public function getTreatedFails($exception) + { + return $this->getFailsFromValidator($exception); + } + + public function getFailsFromValidator($exception) + { + return $exception->validator->failed(); + } } diff --git a/src/config/json-exception-handler.php b/src/config/json-exception-handler.php index 1f67c05..0722bd9 100644 --- a/src/config/json-exception-handler.php +++ b/src/config/json-exception-handler.php @@ -2,57 +2,57 @@ return [ - /* - |--------------------------------------------------------------------------- - | Exceptions Codes - |--------------------------------------------------------------------------- - | - | This values determine the code of each exception. This codes are useful - | to identify the errors generated by your API. You can set your own codes - | and add more fields, validation rules and codes to `validation_fields` - | array. The `default` code is from not managed exceptions. - */ - 'codes' => [ - 'default' => 1, - 'authorization' => 12, - 'model_not_found' => 13, - 'validation' => 14, - 'validation_fields' => [ - 'name' => [ - 'default' => 141, - 'required' => 1411, - 'string' => 1412, - ], - 'email' => [ - 'default' => 142, - 'email' => 1421, - ], - 'password' => [ - 'default' => 143, - 'string' => 1431, - 'confirmed' => 1432, - 'min' => 1433, - ], - ], - 'not_found_http' => 15, - 'authentication' => 16, - 'oauth_server' => 17, - 'bad_request' => 18, - 'client' => [ - 'default' => 19, - 'pagarme' => 20, - 'mailgun' => 21, - ], + /* + |--------------------------------------------------------------------------- + | Exceptions Codes + |--------------------------------------------------------------------------- + | + | This values determine the code of each exception. This codes are useful + | to identify the errors generated by your API. You can set your own codes + | and add more fields, validation rules and codes to `validation_fields` + | array. The `default` code is from not managed exceptions. + */ + 'codes' => [ + 'default' => 1, + 'authorization' => 12, + 'model_not_found' => 13, + 'validation' => 14, + 'validation_fields' => [ + 'name' => [ + 'default' => 141, + 'required' => 1411, + 'string' => 1412, + ], + 'email' => [ + 'default' => 142, + 'email' => 1421, + ], + 'password' => [ + 'default' => 143, + 'string' => 1431, + 'confirmed' => 1432, + 'min' => 1433, + ], ], + 'not_found_http' => 15, + 'authentication' => 16, + 'oauth_server' => 17, + 'bad_request' => 18, + 'client' => [ + 'default' => 19, + 'pagarme' => 20, + 'mailgun' => 21, + ], + ], - /* - |--------------------------------------------------------------------------- - | Default Http Code - |--------------------------------------------------------------------------- - | - | The http code value to not managed exceptions. Generally the code used is - | 500 - Internal Server Error. - */ - 'http_code' => 500, + /* + |--------------------------------------------------------------------------- + | Default Http Code + |--------------------------------------------------------------------------- + | + | The http code value to not managed exceptions. Generally the code used is + | 500 - Internal Server Error. + */ + 'http_code' => 500, ]; diff --git a/src/resources/lang/en/exceptions.php b/src/resources/lang/en/exceptions.php index ed24ee2..0a045e9 100644 --- a/src/resources/lang/en/exceptions.php +++ b/src/resources/lang/en/exceptions.php @@ -2,39 +2,39 @@ return [ - /* - |-------------------------------------------------------------------------- - | Exception Language Lines - |-------------------------------------------------------------------------- - | - | This is the translaction from exceptions - | - */ + /* + |-------------------------------------------------------------------------- + | Exception Language Lines + |-------------------------------------------------------------------------- + | + | This is the translaction from exceptions + | + */ - 'authentication' => [ - 'detail' => 'The request was made by an unauthenticated user.', - ], - 'authorization' => [ - 'title' => 'Action not allowed.', - ], - 'model_not_found' => [ - 'title' => ':Model not found', - ], - 'not_found_http' => [ - 'message' => 'Route not found.', - ], - 'validation' => [ - 'title' => ':Fails validation failed on field :field', - ], - 'client' => [ - 'unavailable' => 'Service unavailable now.', - ], + 'authentication' => [ + 'detail' => 'The request was made by an unauthenticated user.', + ], + 'authorization' => [ + 'title' => 'Action not allowed.', + ], + 'model_not_found' => [ + 'title' => ':Model not found', + ], + 'not_found_http' => [ + 'message' => 'Route not found.', + ], + 'validation' => [ + 'title' => ':Fails validation failed on field :field', + ], + 'client' => [ + 'unavailable' => 'Service unavailable now.', + ], - /* - | Can set your model here to translate the models names on ModelNotFoundException - | - */ - 'models' => [ - 'User' => 'Usuário', - ] + /* + | Can set your model here to translate the models names on ModelNotFoundException + | + */ + 'models' => [ + 'User' => 'Usuário', + ], ]; diff --git a/src/resources/lang/pt-br/exceptions.php b/src/resources/lang/pt-br/exceptions.php index ed24ee2..0a045e9 100644 --- a/src/resources/lang/pt-br/exceptions.php +++ b/src/resources/lang/pt-br/exceptions.php @@ -2,39 +2,39 @@ return [ - /* - |-------------------------------------------------------------------------- - | Exception Language Lines - |-------------------------------------------------------------------------- - | - | This is the translaction from exceptions - | - */ + /* + |-------------------------------------------------------------------------- + | Exception Language Lines + |-------------------------------------------------------------------------- + | + | This is the translaction from exceptions + | + */ - 'authentication' => [ - 'detail' => 'The request was made by an unauthenticated user.', - ], - 'authorization' => [ - 'title' => 'Action not allowed.', - ], - 'model_not_found' => [ - 'title' => ':Model not found', - ], - 'not_found_http' => [ - 'message' => 'Route not found.', - ], - 'validation' => [ - 'title' => ':Fails validation failed on field :field', - ], - 'client' => [ - 'unavailable' => 'Service unavailable now.', - ], + 'authentication' => [ + 'detail' => 'The request was made by an unauthenticated user.', + ], + 'authorization' => [ + 'title' => 'Action not allowed.', + ], + 'model_not_found' => [ + 'title' => ':Model not found', + ], + 'not_found_http' => [ + 'message' => 'Route not found.', + ], + 'validation' => [ + 'title' => ':Fails validation failed on field :field', + ], + 'client' => [ + 'unavailable' => 'Service unavailable now.', + ], - /* - | Can set your model here to translate the models names on ModelNotFoundException - | - */ - 'models' => [ - 'User' => 'Usuário', - ] + /* + | Can set your model here to translate the models names on ModelNotFoundException + | + */ + 'models' => [ + 'User' => 'Usuário', + ], ]; From 16b7ba667877253ddcb4cd99851412d37f567f84 Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Fri, 21 Dec 2018 18:29:08 -0500 Subject: [PATCH 08/14] fix trait not found error --- src/JsonHandler.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/JsonHandler.php b/src/JsonHandler.php index 20a847f..0ea64ad 100644 --- a/src/JsonHandler.php +++ b/src/JsonHandler.php @@ -14,9 +14,7 @@ trait JsonHandler AuthenticationHandler, OAuthServerHandler, MissingScopeHandler, - BadRequestHttpHandler, - ClientHandler, - CieloRequestHandler; + BadRequestHttpHandler; /** * Config file name. From 0ea9754326ddfdfd28decea8c6b13a451b89cec3 Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Fri, 21 Dec 2018 19:09:17 -0500 Subject: [PATCH 09/14] further standardize responses --- .gitignore | 36 +++++++++++++++++-- src/AuthenticationHandler.php | 22 ++++-------- src/AuthorizationHandler.php | 51 ++++----------------------- src/BadRequestHttpHandler.php | 21 ++++------- src/JsonHandler.php | 25 ++++++++----- src/MissingScopeHandler.php | 22 ++++-------- src/ModelNotFoundHandler.php | 22 +++++------- src/NotFoundHttpHandler.php | 29 ++++++--------- src/OAuthServerHandler.php | 22 ++++-------- src/ValidationHandler.php | 19 +++++----- src/config/json-exception-handler.php | 2 ++ 11 files changed, 113 insertions(+), 158 deletions(-) diff --git a/.gitignore b/.gitignore index 81cded9..ffaacb7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,35 @@ -/node_modules /vendor -/.phpintel \ No newline at end of file +/.phpintel + +# Created by https://www.gitignore.io/api/macos +# Edit at https://www.gitignore.io/?templates=macos + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# End of https://www.gitignore.io/api/macos \ No newline at end of file diff --git a/src/AuthenticationHandler.php b/src/AuthenticationHandler.php index e57a6f4..8007dd7 100644 --- a/src/AuthenticationHandler.php +++ b/src/AuthenticationHandler.php @@ -8,21 +8,13 @@ trait AuthenticationHandler { public function authenticationException(AuthenticationException $exception) { - $meta = []; - if (config('json-exception-handler.show_details_in_meta')) { - $meta['__raw_error__'] = [ - 'message' => $exception->getMessage(), - 'backtrace' => explode("\n", $exception->getTraceAsString()), - ]; - } - $error = [[ - 'status' => '401', - 'code' => (string) $this->getCode('authentication'), - 'source' => ['pointer' => $exception->getFile() . ':' . $exception->getLine()], - 'title' => $exception->getMessage(), - 'detail' => __('exception::exceptions.authentication.detail'), - 'meta' => $meta - ]]; + $error = $this->getDefaultError(); + $error['status'] = '401'; + $error['code'] = (string) $this->getCode('authentication'); + $error['title'] = 'authentication'; + $error['detail'] = $exception->getMessage(); + + $error = [$error]; $this->jsonApiResponse->setStatus(401); $this->jsonApiResponse->setErrors($error); diff --git a/src/AuthorizationHandler.php b/src/AuthorizationHandler.php index c7f9ee8..2a538d6 100644 --- a/src/AuthorizationHandler.php +++ b/src/AuthorizationHandler.php @@ -8,52 +8,15 @@ trait AuthorizationHandler { public function authorizationException(AuthorizationException $exception) { - $meta = []; - if (config('json-exception-handler.show_details_in_meta')) { - $meta['__raw_error__'] = [ - 'message' => $exception->getMessage(), - 'backtrace' => explode("\n", $exception->getTraceAsString()), - ]; - } - $error = [[ - 'status' => '403', - 'code' => (string) $this->getCode('authorization'), - 'source' => ['pointer' => $exception->getFile() . ':' . $exception->getLine()], - 'title' => __('exception::exceptions.authorization.title'), - 'detail' => $exception->getMessage(), - 'meta' => $meta - ]]; + $error = $this->getDefaultError(); + $error['status'] = '403'; + $error['code'] = (string) $this->getCode('authorization'); + $error['title'] = 'authorization'; + $error['detail'] = __('exception::exceptions.authorization.title'); + + $error = [$error]; $this->jsonApiResponse->setStatus(403); $this->jsonApiResponse->setErrors($error); } - - public function generateDescription($traces) - { - $action = ''; - foreach ($traces as $trace) { - if ($trace['function'] === 'authorize') { - $action = $this->extractAction($trace['args']); - break; - } - } - } - - public function extractAction($args) - { - $action = reset($args); - - $this->getWord($action); - } - - public function getWords($action) - { - $words = explode('.', $action); - if (!(count($words) > 1)) { - $words = explode('-', $action); - if (!(count($words) > 1)) { - $words = preg_split('/(?=[A-Z])/', $action); - } - } - } } diff --git a/src/BadRequestHttpHandler.php b/src/BadRequestHttpHandler.php index ee24000..4ec0472 100644 --- a/src/BadRequestHttpHandler.php +++ b/src/BadRequestHttpHandler.php @@ -9,21 +9,12 @@ trait BadRequestHttpHandler public function badRequestHttpException(BadRequestHttpException $exception) { $statusCode = $exception->getStatusCode(); - $meta = []; - if (config('json-exception-handler.show_details_in_meta')) { - $meta['__raw_error__'] = [ - 'message' => $exception->getMessage(), - 'backtrace' => explode("\n", $exception->getTraceAsString()), - ]; - } - $error = [[ - 'status' => (string) $statusCode, - 'code' => (string) $this->getCode('bad_request'), - 'source' => ['pointer' => $exception->getFile() . ':' . $exception->getLine()], - 'title' => 'bad_request', - 'detail' => $exception->getMessage(), - 'meta' => $meta - ]]; + $error = $this->getDefaultError(); + $error['status'] = (string) $statusCode; + $error['code'] = (string) $this->getCode('bad_request'); + $error['title'] = 'bad_request'; + $error['detail'] = $exception->getMessage(); + $error = [$error]; $this->jsonApiResponse->setStatus($statusCode); $this->jsonApiResponse->setErrors($error); diff --git a/src/JsonHandler.php b/src/JsonHandler.php index 0ea64ad..c336fe6 100644 --- a/src/JsonHandler.php +++ b/src/JsonHandler.php @@ -34,27 +34,34 @@ trait JsonHandler */ private $exception; - /** - * Set the default response on $response attribute. Get default value from - * methods. - */ - public function setDefaultResponse() + public function getDefaultError() { $meta = []; if (config($this->configFile . '.show_details_in_meta')) { $meta['__raw_error__'] = [ 'message' => $this->getMessage(), + 'detail' => $this->getDescription(), 'backtrace' => explode("\n", $this->exception->getTraceAsString()), ]; } - $error = [[ + $error = [ 'status' => (string) $this->getStatusCode(), 'code' => (string) $this->getCode(), - 'source' => ['pointer' => $this->getDescription()], 'title' => str_replace('Exception', '', class_basename($this->exception)), - 'detail' => $this->getMessage(), + 'detail' => (config($this->configFile . '.show_details_in_meta')) ? $this->getMessage() : 'An unknown error occurred', 'meta' => $meta, - ]]; + ]; + + return $error; + } + + /** + * Set the default response on $response attribute. Get default value from + * methods. + */ + public function setDefaultResponse() + { + $error = [$this->getDefaultError()]; $this->jsonApiResponse->setStatus($this->getStatusCode()); $this->jsonApiResponse->setErrors($error); diff --git a/src/MissingScopeHandler.php b/src/MissingScopeHandler.php index 84f202f..a6144a6 100644 --- a/src/MissingScopeHandler.php +++ b/src/MissingScopeHandler.php @@ -8,21 +8,13 @@ trait MissingScopeHandler { public function missingScopeException(MissingScopeException $exception) { - $meta = []; - if (config('json-exception-handler.show_details_in_meta')) { - $meta['__raw_error__'] = [ - 'message' => $exception->getMessage(), - 'backtrace' => explode("\n", $exception->getTraceAsString()), - ]; - } - $error = [[ - 'status' => '403', - 'code' => (string) $this->getCode('missing_scope'), - 'source' => ['pointer' => $exception->getFile() . ':' . $exception->getLine()], - 'title' => 'missing_scope', - 'detail' => $exception->getMessage(), - 'meta' => $meta, - ]]; + $error = $this->getDefaultError(); + $error['status'] = '403'; + $error['code'] = (string) $this->getCode('missing_scope'); + $error['title'] = 'missing_scope'; + $error['detail'] = $exception->getMessage(); + + $error = [$error]; $this->jsonApiResponse->setStatus(403); $this->jsonApiResponse->setErrors($error); diff --git a/src/ModelNotFoundHandler.php b/src/ModelNotFoundHandler.php index b975f2f..7bfc8c8 100644 --- a/src/ModelNotFoundHandler.php +++ b/src/ModelNotFoundHandler.php @@ -21,21 +21,15 @@ public function modelNotFoundException(ModelNotFoundException $exception) 'attribute' => 'id' ]; - if (config('json-exception-handler.show_details_in_meta')) { - $meta['__raw_error__'] = [ - 'message' => $exception->getMessage(), - 'backtrace' => explode("\n", $exception->getTraceAsString()), - ]; - } - $error = [[ - 'status' => '404', - 'code' => (string) $this->getCode('model_not_found'), - 'source' => ['pointer' => 'data/id'], - 'title' => $exception->getMessage(), - 'detail' => __('exception::exceptions.model_not_found.title', ['model' => $entity]), - 'meta' => $meta - ]]; + $error = $this->getDefaultError(); + $error['status'] = '404'; + $error['code'] = (string) $this->getCode('model_not_found'); + $error['title'] = 'model_not_found'; + $error['detail'] = __('exception::exceptions.model_not_found.title', ['model' => $entity]); + $error['meta']['attribute'] = 'id'; + + $error = [$error]; $this->jsonApiResponse->setStatus(404); $this->jsonApiResponse->setErrors($error); diff --git a/src/NotFoundHttpHandler.php b/src/NotFoundHttpHandler.php index 15bcb41..1ce05c2 100644 --- a/src/NotFoundHttpHandler.php +++ b/src/NotFoundHttpHandler.php @@ -13,24 +13,17 @@ trait NotFoundHttpHandler */ public function notFoundHttpException(NotFoundHttpException $exception) { - $statuCode = $exception->getStatusCode(); - $meta = []; - if (config('json-exception-handler.show_details_in_meta')) { - $meta['__raw_error__'] = [ - 'message' => $exception->getMessage(), - 'backtrace' => explode("\n", $exception->getTraceAsString()), - ]; - } - $error = [[ - 'status' => (string) $statuCode, - 'code' => (string) $this->getCode('not_found_http'), - 'source' => ['pointer' => request()->path()], - 'title' => $this->getDescription($exception), - 'detail' => $this->getNotFoundMessage($exception), - 'meta' => $meta - ]]; - - $this->jsonApiResponse->setStatus($statuCode); + $statusCode = $exception->getStatusCode(); + + $error = $this->getDefaultError(); + $error['status'] = (string) $statusCode; + $error['code'] = (string) $this->getCode('not_found_http'); + $error['title'] = $this->getDescription($exception); + $error['detail'] = $this->getNotFoundMessage($exception); + + $error = [$error]; + + $this->jsonApiResponse->setStatus($statusCode); $this->jsonApiResponse->setErrors($error); } diff --git a/src/OAuthServerHandler.php b/src/OAuthServerHandler.php index 2a03b39..870a8ad 100644 --- a/src/OAuthServerHandler.php +++ b/src/OAuthServerHandler.php @@ -9,22 +9,14 @@ trait OAuthServerHandler public function oAuthServerException(OAuthServerException $exception) { $statusCode = $exception->getHttpStatusCode(); - $meta = []; - if (config('json-exception-handler.show_details_in_meta')) { - $meta['__raw_error__'] = [ - 'message' => $exception->getMessage(), - 'backtrace' => explode("\n", $exception->getTraceAsString()), - ]; - } - $error = [[ - 'status' => (string) $statusCode, - 'code' => (string) $this->getCode('not_found_http'), - 'source' => ['pointer' => $exception->getFile() . ':' . $exception->getLine()], - 'title' => $exception->getErrorType(), - 'detail' => $exception->getMessage(), - 'meta' => $meta - ]]; + $error = $this->getDefaultError(); + $error['status'] = (string) $statusCode; + $error['code'] = (string) $this->getCode('oauth_server'); + $error['title'] = 'authenticating'; + $error['detail'] = $exception->getErrorType(); + + $error = [$error]; $this->jsonApiResponse->setStatus($statusCode); $this->jsonApiResponse->setErrors($error); diff --git a/src/ValidationHandler.php b/src/ValidationHandler.php index be8b825..6164b31 100644 --- a/src/ValidationHandler.php +++ b/src/ValidationHandler.php @@ -39,17 +39,14 @@ public function jsonApiFormatErrorMessages(ValidationException $exception) foreach ($messages as $key => $message) { $attributes = $this->getValidationAttributes($validationFails, $key, $field); $path = str_replace('/', ':', request()->path()); - $error = [ - 'status' => '422', - 'code' => "V:{$path}::{$field}", - 'source' => ['parameter' => $field], - 'title' => $attributes['title'], - 'detail' => $message, - 'meta' => [ - 'attribute' => $field, - 'message' => $message - ] - ]; + $error = $this->getDefaultError(); + $error['status'] = '422'; + $error['code'] = "V:{$path}::{$field}"; + $error['source'] = ['parameter' => $field]; + $error['title'] = $attributes['title']; + $error['detail'] = $message; + $error['meta']['attribute'] = $field; + $error['meta']['message'] = $message; array_push($errors, $error); } } diff --git a/src/config/json-exception-handler.php b/src/config/json-exception-handler.php index 0722bd9..8e94f38 100644 --- a/src/config/json-exception-handler.php +++ b/src/config/json-exception-handler.php @@ -45,6 +45,8 @@ ], ], + 'show_details_in_meta' => (env('APP_ENV', 'production') !== 'production'), + /* |--------------------------------------------------------------------------- | Default Http Code From e9c0352a93b0a0a644b1ce33e64b526d6754cc62 Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Thu, 3 Jan 2019 12:19:08 -0500 Subject: [PATCH 10/14] Support for manual call to ValidationException::withMessages() --- src/ValidationHandler.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ValidationHandler.php b/src/ValidationHandler.php index 6164b31..f9b7819 100644 --- a/src/ValidationHandler.php +++ b/src/ValidationHandler.php @@ -33,7 +33,6 @@ public function jsonApiFormatErrorMessages(ValidationException $exception) { $validationMessages = $this->getTreatedMessages($exception); $validationFails = $this->getTreatedFails($exception); - $errors = []; foreach ($validationMessages as $field => $messages) { foreach ($messages as $key => $message) { @@ -64,15 +63,20 @@ public function getValidationAttributes(array $validationFails, $key, $field) public function getValidationTitle(array $validationFails, $key, $field) { - return __('exception::exceptions.validation.title', [ - 'fails' => array_keys($validationFails[$field])[$key], + if (array_key_exists($field, $validationFails)) { + return __('exception::exceptions.validation.title', [ + 'fails' => array_keys($validationFails[$field])[$key], + 'field' => $field, + ]); + } + return __('exception::exceptions.validation.generic_title', [ 'field' => $field, ]); } public function getValidationCode(array $validationFails, $key, $field) { - $rule = strtolower(array_keys($validationFails[$field])[$key]); + $rule = (array_key_exists($field, $validationFails)) ? strtolower(array_keys($validationFails[$field])[$key]) : 'default'; return config($this->configFile . '.codes.validation_fields.' . $field . '.' . $rule); } From 5549bda341a9f9bd64c60c018723be1dd0d0e1f2 Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Tue, 18 Jun 2019 11:10:20 -0400 Subject: [PATCH 11/14] feat: Utilize json_options from config for response --- src/JsonHandler.php | 4 +++- src/config/json-exception-handler.php | 3 +++ src/resources/lang/en/exceptions.php | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/JsonHandler.php b/src/JsonHandler.php index c336fe6..e54802e 100644 --- a/src/JsonHandler.php +++ b/src/JsonHandler.php @@ -142,7 +142,9 @@ public function jsonResponse(Exception $exception) return response()->json( $this->jsonApiResponse->toArray(), - $this->jsonApiResponse->getStatus() + $this->jsonApiResponse->getStatus(), + config($this->configFile . '.additional_headers'), + config($this->configFile . '.json_options') ); } diff --git a/src/config/json-exception-handler.php b/src/config/json-exception-handler.php index 8e94f38..6f22077 100644 --- a/src/config/json-exception-handler.php +++ b/src/config/json-exception-handler.php @@ -45,6 +45,9 @@ ], ], + 'additional_headers' => [], + 'json_options' => JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES, + 'show_details_in_meta' => (env('APP_ENV', 'production') !== 'production'), /* diff --git a/src/resources/lang/en/exceptions.php b/src/resources/lang/en/exceptions.php index 0a045e9..882f807 100644 --- a/src/resources/lang/en/exceptions.php +++ b/src/resources/lang/en/exceptions.php @@ -25,6 +25,7 @@ ], 'validation' => [ 'title' => ':Fails validation failed on field :field', + 'generic_title' => 'Validation failed on field :field', ], 'client' => [ 'unavailable' => 'Service unavailable now.', From da5cb8e37ca4c0a29331af458ffa4716171fa829 Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Fri, 6 Dec 2019 13:29:42 -0500 Subject: [PATCH 12/14] fix(oauth): pass message as detail --- src/OAuthServerHandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OAuthServerHandler.php b/src/OAuthServerHandler.php index 870a8ad..452bfca 100644 --- a/src/OAuthServerHandler.php +++ b/src/OAuthServerHandler.php @@ -13,8 +13,8 @@ public function oAuthServerException(OAuthServerException $exception) $error = $this->getDefaultError(); $error['status'] = (string) $statusCode; $error['code'] = (string) $this->getCode('oauth_server'); - $error['title'] = 'authenticating'; - $error['detail'] = $exception->getErrorType(); + $error['title'] = 'auth:' . $exception->getErrorType(); + $error['detail'] = $exception->getMessage(); $error = [$error]; From 8353881057caa7946b70f148744c8d4bac09f97b Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Sat, 22 Aug 2020 13:23:44 -0400 Subject: [PATCH 13/14] fix: switch from Exception to Throwable --- README.md | 2 +- composer.json | 2 +- src/JsonHandler.php | 44 ++++++++++++++++++++++---------------------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 9570d63..0eef271 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ class Handler extends ExceptionHandler ... - public function render($request, Exception $exception) + public function render($request, \Throwable $exception) { if ($request->expectsJson()) { return $this->jsonResponse($exception); diff --git a/composer.json b/composer.json index 6794ccd..77d3791 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ } ], "require": { - "php": ">=5.6.4" + "php": ">=7.1.0" }, "autoload": { "psr-4": { diff --git a/src/JsonHandler.php b/src/JsonHandler.php index e54802e..a4e669d 100644 --- a/src/JsonHandler.php +++ b/src/JsonHandler.php @@ -2,7 +2,7 @@ namespace SMartins\JsonHandler; -use Exception; +use Throwable; use SMartins\JsonHandler\Responses\JsonApiResponse; trait JsonHandler @@ -30,9 +30,9 @@ trait JsonHandler /** * Receive exception instance to be used on methods. - * @var Exception + * @var Throwable */ - private $exception; + private $throwable; public function getDefaultError() { @@ -41,13 +41,13 @@ public function getDefaultError() $meta['__raw_error__'] = [ 'message' => $this->getMessage(), 'detail' => $this->getDescription(), - 'backtrace' => explode("\n", $this->exception->getTraceAsString()), + 'backtrace' => explode("\n", $this->throwable->getTraceAsString()), ]; } $error = [ 'status' => (string) $this->getStatusCode(), 'code' => (string) $this->getCode(), - 'title' => str_replace('Exception', '', class_basename($this->exception)), + 'title' => str_replace('Throwable', '', class_basename($this->throwable)), 'detail' => (config($this->configFile . '.show_details_in_meta')) ? $this->getMessage() : 'An unknown error occurred', 'meta' => $meta, ]; @@ -70,11 +70,11 @@ public function setDefaultResponse() /** * Get default message from exception. * - * @return string Exception message + * @return string Throwable message */ public function getMessage() { - return $this->exception->getMessage(); + return $this->throwable->getMessage(); } /** @@ -84,9 +84,9 @@ public function getMessage() */ public function getDescription() { - return class_basename($this->exception) . - ' line ' . $this->exception->getLine() . - ' in ' . $this->exception->getFile(); + return class_basename($this->throwable) . + ' line ' . $this->throwable->getLine() . + ' in ' . $this->throwable->getFile(); } /** @@ -97,8 +97,8 @@ public function getDescription() */ public function getStatusCode() { - if (method_exists($this->exception, 'getStatusCode')) { - $httpCode = $this->exception->getStatusCode(); + if (method_exists($this->throwable, 'getStatusCode')) { + $httpCode = $this->throwable->getStatusCode(); } else { $httpCode = config($this->configFile . '.http_code'); } @@ -114,8 +114,8 @@ public function getStatusCode() */ public function getCode($type = 'default') { - $code = $this->exception->getCode(); - if (empty($this->exception->getCode())) { + $code = $this->throwable->getCode(); + if (empty($this->throwable->getCode())) { $code = config($this->configFile . '.codes.' . $type); } @@ -126,12 +126,12 @@ public function getCode($type = 'default') * Handle the json response. Check if exception is treated. If true call * the specific handler. If false set the default response to be returned. * - * @param Exception $exception + * @param Throwable $exception * @return JsonResponse */ - public function jsonResponse(Exception $exception) + public function jsonResponse(Throwable $exception) { - $this->exception = $exception; + $this->throwable = $exception; $this->jsonApiResponse = new JsonApiResponse; if ($this->exceptionIsTreated()) { @@ -151,7 +151,7 @@ public function jsonResponse(Exception $exception) /** * Check if method to treat exception exists. * - * @param Exception $exception The exception to be checked + * @param Throwable $exception The exception to be checked * @return bool If method is callable */ public function exceptionIsTreated() @@ -162,22 +162,22 @@ public function exceptionIsTreated() /** * Call the exception handler after of to check if the method exists. * - * @param Exception $exception + * @param Throwable $exception * @return void Call the method */ public function callExceptionHandler() { - $this->{$this->methodName()}($this->exception); + $this->{$this->methodName()}($this->throwable); } /** * The method name is the exception name with first letter in lower case. * - * @param Exception $exception + * @param Throwable $exception * @return string The method name */ public function methodName() { - return lcfirst(class_basename($this->exception)); + return lcfirst(class_basename($this->throwable)); } } From a0fc8ebd9352227e24941937e560280e76fdf104 Mon Sep 17 00:00:00 2001 From: Cody Carrell Date: Fri, 29 Jan 2021 15:10:16 -0500 Subject: [PATCH 14/14] fix: correct implode parameter order --- src/ModelNotFoundHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ModelNotFoundHandler.php b/src/ModelNotFoundHandler.php index 7bfc8c8..5609dce 100644 --- a/src/ModelNotFoundHandler.php +++ b/src/ModelNotFoundHandler.php @@ -15,7 +15,7 @@ public function modelNotFoundException(ModelNotFoundException $exception) { $entity = $this->extractEntityName($exception->getModel()); - $ids = implode($exception->getIds(), ','); + $ids = implode(',', $exception->getIds()); $meta = [ 'attribute' => 'id'