1 | <?php |
||
2 | |||
3 | namespace W2w\Laravel\Apie\Services; |
||
4 | |||
5 | use Exception; |
||
6 | use Illuminate\Http\Request; |
||
7 | use Illuminate\Support\Str; |
||
8 | use Illuminate\Validation\ValidationException; |
||
9 | use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory; |
||
10 | use Symfony\Component\HttpFoundation\Response; |
||
11 | use Symfony\Component\HttpKernel\Exception\HttpException; |
||
12 | use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException; |
||
13 | use W2w\Lib\Apie\Core\Models\ApiResourceFacadeResponse; |
||
14 | use W2w\Lib\Apie\Exceptions\ValidationException as ApieValidationException; |
||
15 | use W2w\Lib\Apie\Interfaces\ResourceSerializerInterface; |
||
16 | |||
17 | class ApieExceptionToResponse |
||
18 | { |
||
19 | private $httpFoundationFactory; |
||
20 | |||
21 | private $exceptionMapping; |
||
22 | |||
23 | public function __construct(HttpFoundationFactory $httpFoundationFactory, array $exceptionMapping) |
||
24 | { |
||
25 | $this->httpFoundationFactory = $httpFoundationFactory; |
||
26 | $this->exceptionMapping = $exceptionMapping; |
||
27 | } |
||
28 | |||
29 | public function convertExceptionToApieResponse(Request $request, Exception $exception): Response |
||
30 | { |
||
31 | $statusCode = 500; |
||
32 | if ($exception instanceof HttpException) { |
||
33 | $statusCode = $exception->getStatusCode(); |
||
34 | } |
||
35 | $statusCode = $this->getStatusCodeFromClassMapping(get_class($exception)) ?? $statusCode; |
||
36 | |||
37 | if ($exception instanceof ValidationException) { |
||
38 | $statusCode = 422; |
||
39 | $exception = new ApieValidationException($exception->errors()); |
||
0 ignored issues
–
show
Deprecated Code
introduced
by
![]() |
|||
40 | } |
||
41 | $apiRes = new ApiResourceFacadeResponse( |
||
42 | app(ResourceSerializerInterface::class), |
||
43 | $exception, |
||
44 | $request->header('accept') |
||
45 | ); |
||
46 | try { |
||
47 | $response = $apiRes->getResponse(); |
||
48 | } catch (NotAcceptableHttpException $notAcceptableHttpException) { |
||
49 | // accept header is not allowed, so assume to return default accept header. |
||
50 | $apiRes = new ApiResourceFacadeResponse( |
||
51 | app(ResourceSerializerInterface::class), |
||
52 | $exception, |
||
53 | null |
||
54 | ); |
||
55 | $response = $apiRes->getResponse(); |
||
56 | } |
||
57 | return $this->httpFoundationFactory->createResponse($response->withStatus($statusCode)); |
||
58 | } |
||
59 | |||
60 | public function isApieAction(Request $request): bool |
||
61 | { |
||
62 | $route = $request->route(); |
||
63 | if (!$route) { |
||
64 | return false; |
||
65 | } |
||
66 | // needed for Lumen |
||
67 | if (is_array($route)) { |
||
0 ignored issues
–
show
|
|||
68 | $name = $route['1']['as'] ?? ''; |
||
69 | return Str::startsWith($name, 'apie.'); |
||
70 | } |
||
71 | return Str::startsWith($route->getName(), 'apie.'); |
||
72 | } |
||
73 | |||
74 | private function getStatusCodeFromClassMapping(string $className): ?int |
||
75 | { |
||
76 | if (isset($this->exceptionMapping[$className])) { |
||
77 | return (int) $this->exceptionMapping[$className]; |
||
78 | } else { |
||
79 | foreach ($this->exceptionMapping as $mappedClassName => $intendedStatusCode) { |
||
80 | if (is_a($className, $mappedClassName, true)) { |
||
81 | return (int) $intendedStatusCode; |
||
82 | } |
||
83 | } |
||
84 | } |
||
85 | return null; |
||
86 | } |
||
87 | } |
||
88 |