]> BookStack Code Mirror - bookstack/blob - app/Exceptions/Handler.php
fix image delete confirm text
[bookstack] / app / Exceptions / Handler.php
1 <?php
2
3 namespace BookStack\Exceptions;
4
5 use Exception;
6 use Illuminate\Auth\Access\AuthorizationException;
7 use Illuminate\Auth\AuthenticationException;
8 use Illuminate\Database\Eloquent\ModelNotFoundException;
9 use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
10 use Illuminate\Http\JsonResponse;
11 use Illuminate\Http\Request;
12 use Illuminate\Validation\ValidationException;
13 use Symfony\Component\HttpKernel\Exception\HttpException;
14 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
15
16 class Handler extends ExceptionHandler
17 {
18     /**
19      * A list of the exception types that should not be reported.
20      *
21      * @var array
22      */
23     protected $dontReport = [
24         AuthorizationException::class,
25         HttpException::class,
26         ModelNotFoundException::class,
27         ValidationException::class,
28         NotFoundException::class,
29     ];
30
31     /**
32      * Report or log an exception.
33      * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
34      *
35      * @param  \Exception $e
36      * @return mixed
37      * @throws Exception
38      */
39     public function report(Exception $e)
40     {
41         return parent::report($e);
42     }
43
44     /**
45      * Render an exception into an HTTP response.
46      *
47      * @param  \Illuminate\Http\Request $request
48      * @param  \Exception $e
49      * @return \Illuminate\Http\Response
50      */
51     public function render($request, Exception $e)
52     {
53         if ($this->isApiRequest($request)) {
54             return $this->renderApiException($e);
55         }
56
57         // Handle notify exceptions which will redirect to the
58         // specified location then show a notification message.
59         if ($this->isExceptionType($e, NotifyException::class)) {
60             $message = $this->getOriginalMessage($e);
61             if (!empty($message)) {
62                 session()->flash('error', $message);
63             }
64             return redirect($e->redirectLocation);
65         }
66
67         // Handle pretty exceptions which will show a friendly application-fitting page
68         // Which will include the basic message to point the user roughly to the cause.
69         if ($this->isExceptionType($e, PrettyException::class)  && !config('app.debug')) {
70             $message = $this->getOriginalMessage($e);
71             $code = ($e->getCode() === 0) ? 500 : $e->getCode();
72             return response()->view('errors/' . $code, ['message' => $message], $code);
73         }
74
75         // Handle 404 errors with a loaded session to enable showing user-specific information
76         if ($this->isExceptionType($e, NotFoundHttpException::class)) {
77             return \Route::respondWithRoute('fallback');
78         }
79
80         return parent::render($request, $e);
81     }
82
83     /**
84      * Check if the given request is an API request.
85      */
86     protected function isApiRequest(Request $request): bool
87     {
88         return strpos($request->path(), 'api/') === 0;
89     }
90
91     /**
92      * Render an exception when the API is in use.
93      */
94     protected function renderApiException(Exception $e): JsonResponse
95     {
96         $code = $e->getCode() === 0 ? 500 : $e->getCode();
97         $headers = [];
98         if ($e instanceof HttpException) {
99             $code = $e->getStatusCode();
100             $headers = $e->getHeaders();
101         }
102
103         $responseData = [
104             'error' => [
105                 'message' => $e->getMessage(),
106             ]
107         ];
108
109         if ($e instanceof ValidationException) {
110             $responseData['error']['validation'] = $e->errors();
111             $code = $e->status;
112         }
113
114         $responseData['error']['code'] = $code;
115         return new JsonResponse($responseData, $code, $headers);
116     }
117
118     /**
119      * Check the exception chain to compare against the original exception type.
120      * @param Exception $e
121      * @param $type
122      * @return bool
123      */
124     protected function isExceptionType(Exception $e, $type)
125     {
126         do {
127             if (is_a($e, $type)) {
128                 return true;
129             }
130         } while ($e = $e->getPrevious());
131         return false;
132     }
133
134     /**
135      * Get original exception message.
136      * @param Exception $e
137      * @return string
138      */
139     protected function getOriginalMessage(Exception $e)
140     {
141         do {
142             $message = $e->getMessage();
143         } while ($e = $e->getPrevious());
144         return $message;
145     }
146
147     /**
148      * Convert an authentication exception into an unauthenticated response.
149      *
150      * @param  \Illuminate\Http\Request  $request
151      * @param  \Illuminate\Auth\AuthenticationException  $exception
152      * @return \Illuminate\Http\Response
153      */
154     protected function unauthenticated($request, AuthenticationException $exception)
155     {
156         if ($request->expectsJson()) {
157             return response()->json(['error' => 'Unauthenticated.'], 401);
158         }
159
160         return redirect()->guest('login');
161     }
162
163     /**
164      * Convert a validation exception into a JSON response.
165      *
166      * @param  \Illuminate\Http\Request  $request
167      * @param  \Illuminate\Validation\ValidationException  $exception
168      * @return \Illuminate\Http\JsonResponse
169      */
170     protected function invalidJson($request, ValidationException $exception)
171     {
172         return response()->json($exception->errors(), $exception->status);
173     }
174 }
Morty Proxy This is a proxified and sanitized view of the page, visit original site.