Passed
Push — 2.0 ( 50041b...cfd0e0 )
by Samuel
02:05
created

AbstractHandler::getDefaultPointer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SMartins\Exceptions\Handlers;
4
5
use Exception;
6
use RuntimeException;
7
use InvalidArgumentException;
8
use Illuminate\Support\Collection;
9
use SMartins\Exceptions\JsonApi\Error;
10
use SMartins\Exceptions\JsonApi\Response;
11
use Illuminate\Auth\AuthenticationException;
12
use Illuminate\Validation\ValidationException;
13
use SMartins\Exceptions\JsonApi\ErrorCollection;
14
use Illuminate\Auth\Access\AuthorizationException;
15
use Illuminate\Database\Eloquent\ModelNotFoundException;
16
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
17
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
18
19
abstract class AbstractHandler
20
{
21
    /**
22
     * The exception thrown.
23
     *
24
     * @var \Exception
25
     */
26
    protected $exception;
27
28
    /**
29
     * An array where the key is the class exception and the value is the handler
30
     * class that will treat the exception.
31
     *
32
     * @var array
33
     */
34
    protected $exceptionHandlers = [];
35
36
    /**
37
     * An internal array where the key is the exception class and the value is
38
     * the handler class that will treat the exception.
39
     *
40
     * @var array
41
     */
42
    protected $internalExceptionHandlers = [
43
        Exception::class => Handler::class,
44
        ModelNotFoundException::class => ModelNotFoundHandler::class,
45
        AuthenticationException::class => AuthenticationHandler::class,
46
        AuthorizationException::class => AuthorizationHandler::class,
47
        AuthorizationException::class => AuthorizationHandler::class,
48
        ValidationException::class => ValidationHandler::class,
49
        BadRequestHttpException::class => BadRequestHttpHandler::class,
50
        NotFoundHttpException::class => NotFoundHttpHandler::class,
51
        'Laravel\Passport\Exceptions\MissingScopeException' => MissingScopeHandler::class,
52
        'League\OAuth2\Server\Exception\OAuthServerException' => OAuthServerHandler::class,
53
    ];
54
55
    /**
56
     * Create instance using the Exception to be handled.
57
     *
58
     * @param Exception $e
59
     */
60
    public function __construct(Exception $e)
61
    {
62
        $this->exception = $e;
63
    }
64
65
    /**
66
     * Handle with an exception according to specific definitions. Returns one
67
     * or more errors using the exception from $exceptions attribute.
68
     *
69
     * @return \SMartins\Exceptions\JsonApi\Error|\Smartins\Exceptions\JsonApi\ErrorCollection|array|\Illuminate\Support\Collection
70
     */
71
    abstract public function handle();
72
73
    /**
74
     * Get error code. If code is empty from config file based on type.
75
     *
76
     * @param  string $type Code type from config file
77
     * @return int
78
     */
79
    public function getCode($type = 'default')
80
    {
81
        $code = $this->exception->getCode();
82
        if (empty($this->exception->getCode())) {
83
            $code = config('json-exception-handler.codes.'.$type);
84
        }
85
86
        return $code;
87
    }
88
89
    /**
90
     * Return response with handled exception.
91
     *
92
     * @return \SMartins\Exceptions\JsonApi\Response
93
     */
94
    public function handleException()
95
    {
96
        $handler = $this->getExceptionHandler();
97
98
        $errors = $this->validatedHandledException($handler->handle());
99
100
        return new Response($errors);
101
    }
102
103
    /**
104
     * Validate response from handle method of handler class.
105
     *
106
     * @param  mixed $errors
107
     * @return \SMartins\Exceptions\JsonApi\ErrorCollection
108
     *
109
     * @throws \InvalidArgumentException
110
     */
111
    public function validatedHandledException($errors)
112
    {
113
        if (is_array($errors) || get_class($errors) === Collection::class) {
114
            $errors = new ErrorCollection($errors);
115
        } elseif ($errors instanceof Error) {
116
            $errors = (new ErrorCollection)->push($errors)->setStatusCode($errors->getStatus());
117
        }
118
119
        if (! $errors instanceof ErrorCollection) {
120
            throw new InvalidArgumentException('The errors must be an array, ['.Collection::class.'], ['.Error::class.'] or ['.ErrorCollection::class.'].');
121
        }
122
123
        return $errors->validated();
124
    }
125
126
    /**
127
     * Get the class the will handle the Exception from exceptionHandlers attributes.
128
     *
129
     * @return mixed
130
     */
131
    public function getExceptionHandler()
132
    {
133
        $handlers = array_merge($this->exceptionHandlers, $this->internalExceptionHandlers);
134
135
        $handler = isset($handlers[get_class($this->exception)])
136
            ? $handlers[get_class($this->exception)]
137
            : $this->defaultHandler();
138
139
        return new $handler($this->exception);
140
    }
141
142
    /**
143
     * Get default pointer using file and line of exception.
144
     *
145
     * @return string
146
     */
147
    public function getDefaultPointer()
148
    {
149
        return $this->exception->getFile().':'.$this->exception->getLine();
150
    }
151
152
    /**
153
     * Get default title from exception.
154
     *
155
     * @return string
156
     */
157
    public function getDefaultTitle()
158
    {
159
        return snake_case(class_basename($this->exception));
160
    }
161
162
    /**
163
     * Get default http code. Check if exception has getStatusCode() methods.
164
     * If not get from config file.
165
     *
166
     * @return int
167
     */
168
    public function getStatusCode()
169
    {
170
        if (method_exists($this->exception, 'getStatusCode')) {
171
            return $this->exception->getStatusCode();
172
        }
173
174
        return config('json-exception-handler.http_code');
175
    }
176
177
    /**
178
     * The default handler to handle not treated exceptions.
179
     *
180
     * @return \SMartins\Exceptions\Handlers\Handler
181
     */
182
    public function defaultHandler()
183
    {
184
        return new Handler($this->exception);
185
    }
186
}
187