Passed
Push — feature/optimize ( 0d9399...d24737 )
by Fu
02:58
created

Handler::parserTokenExpiredException()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 2
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Modules\Core\Supports;
4
5
use Exception;
6
use Illuminate\Database\Eloquent\ModelNotFoundException;
7
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
8
use Modules\Core\Enums\StatusCodeEnum;
9
use Modules\Core\ErrorCodes\JWTErrorCode;
10
use Symfony\Component\HttpKernel\Exception\{
11
    HttpException, UnauthorizedHttpException
12
};
13
use Tymon\JWTAuth\Exceptions\{
14
    InvalidClaimException,
15
    JWTException,
16
    PayloadException,
17
    TokenBlacklistedException,
18
    TokenExpiredException,
19
    TokenInvalidException,
20
    UserNotDefinedException
21
};
22
23
class Handler extends ExceptionHandler
24
{
25
    const STATUS_CODE = 'status_code';
26
    const ERROR_CODE = 'error_code';
27
    const MESSAGE = 'message';
28
    const DEBUG = 'debug';
29
30
    /**
31
     * Render an exception into an HTTP response.
32
     *
33
     * @param \Illuminate\Http\Request $request
34
     * @param \Exception|HttpException $exception
35
     *
36
     * @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
37
     */
38
    public function render($request, Exception $exception)
39
    {
40
        if ($request->is('api/*') || $request->wantsJson()) {
41
            if ('web' !== config('core.api.error_format')) {
42
                $response = [];
43
                $exceptionClass = get_class($exception);
44
                $exception = $this->overwrite($exception);
45
46
                if ($exception instanceof ModelNotFoundException) {
47
                    $response = $this->parserModelNotFoundException($response, $exception);
48
                } elseif ($exception instanceof JWTException) {
49
                    $response = $this->parserJWTException($response, $exception, $exceptionClass);
50
                } else {
51
                    $response = $this->parserException($response, $exception, $exceptionClass);
52
                }
53
54
                $response = $this->debug($response, $exception);
55
56
                return $this->response(collect($response)->toArray());
57
            }
58
        }
59
60
        return parent::render($request, $exception);
61
    }
62
63
    protected function response(array $response)
64
    {
65
        return (new Response($response))->render();
66
    }
67
68
    protected function debug(array $response, Exception $exception)
69
    {
70
        if (true === config('app.debug')) {
71
            $response['meta'][self::DEBUG]['file'] = $exception->getFile();
72
            $response['meta'][self::DEBUG]['line'] = $exception->getLine();
73
            $response['meta'][self::DEBUG]['trace'] = $exception->getTrace();
74
        }
75
76
        return $response;
77
    }
78
79
    protected function overwrite(Exception $exception)
80
    {
81
        if ($exception instanceof UnauthorizedHttpException && method_exists($exception, 'getPrevious')) {
82
            $exception = $exception->getPrevious();
83
        }
84
85
        return $exception;
86
    }
87
88
    protected function parserModelNotFoundException(
89
        array $response,
90
        Exception $exception
91
    ): array {
92
        $response['meta'][self::STATUS_CODE] = StatusCodeEnum::HTTP_NOT_FOUND;
93
        $response['meta'][self::MESSAGE] = $exception->getMessage();
94
95
        return $response;
96
    }
97
98
    protected function parserJWTException(array $response, Exception $exception, string $exceptionClass): array
99
    {
100
        switch ($exceptionClass) {
101
            case InvalidClaimException::class:
102
                $response['meta'][self::ERROR_CODE] = JWTErrorCode::INVALID_CLAIM;
103
                break;
104
105
            case PayloadException::class:
106
                $response['meta'][self::ERROR_CODE] = JWTErrorCode::PAYLOAD;
107
                break;
108
109
            case TokenBlacklistedException::class:
110
                $response['meta'][self::ERROR_CODE] = JWTErrorCode::TOKEN_BLACKLISTED;
111
                break;
112
113
            case TokenExpiredException::class:
114
                $response = $this->parserTokenExpiredException($response, $exception);
115
                break;
116
117
            case TokenInvalidException::class:
118
                $response['meta'][self::ERROR_CODE] = JWTErrorCode::TOKEN_INVALID;
119
                break;
120
121
            case UserNotDefinedException::class:
122
                $response['meta'][self::ERROR_CODE] = JWTErrorCode::USER_NOT_DEFINED;
123
                break;
124
125
            default:
126
                $response['meta'][self::ERROR_CODE] = JWTErrorCode::DEFAULT;;
127
        }
128
129
        $response['meta'][self::STATUS_CODE] = StatusCodeEnum::HTTP_UNAUTHORIZED;
130
        $response['meta'][self::MESSAGE] = $exception->getMessage();
131
132
        return $response;
133
    }
134
135
    protected function parserTokenExpiredException(array $response, Exception $exception)
136
    {
137
        if ('Token has expired and can no longer be refreshed' === $exception->getMessage()) {
138
            $response['meta'][self::ERROR_CODE] = JWTErrorCode::CAN_NOT_REFRESHED;
139
        } else {
140
            $response['meta'][self::ERROR_CODE] = JWTErrorCode::TOKEN_EXPIRED;
141
        }
142
143
        return $response;
144
    }
145
146
    protected function parserException(array $response, Exception $exception, string $exceptionClass): array
147
    {
148
        if (method_exists($exception, 'getStatusCode')) {
149
            $response['meta'][self::STATUS_CODE] = $exception->getStatusCode();
150
        } else {
151
            $response['meta'][self::STATUS_CODE] = StatusCodeEnum::HTTP_INTERNAL_SERVER_ERROR;
152
        }
153
154
        if (method_exists($exception, 'getCode')) {
155
            $response['meta'][self::ERROR_CODE] = $exception->getCode();
156
        }
157
158
        if (null === $exception->getMessage()) {
159
            $response['meta'][self::MESSAGE] = class_basename($exceptionClass);
160
        } else {
161
            $response['meta'][self::MESSAGE] = $exception->getMessage();
162
        }
163
164
        return $response;
165
    }
166
}
167