ldc-dam/app/Exceptions/Handler.php
2022-07-29 13:12:34 +02:00

184 lines
6.2 KiB
PHP

<?php
namespace App\Exceptions;
use App\Enums\Legacy\ApiError;
use App\Enums\Legacy\ApiStatus;
use App\Exceptions\Api\ApiErrorException;
use App\Http\Resources\Api\ApiResponse as ApiResponseResource;
use App\Lib\Helper;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Exceptions\ThrottleRequestsException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of exception types with their corresponding custom log levels.
*
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
*/
protected $levels = [
ApiErrorException::class => \Psr\Log\LogLevel::WARNING
];
/**
* A list of the exception types that are not reported.
*
* @var array<int, class-string<\Throwable>>
*/
protected $dontReport = [
ApiErrorException::class,
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (Throwable $e) {
});
}
/**
* Render an exception into an HTTP response.
*
* @param mixed $request
* @param \Throwable $e
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Throwable If needed.
*/
public function render(mixed $request, Throwable $e)
{
if (Helper::isRequestForApi($request) and $request->isJson()) {
return $this->handleApiException($request, $e);
} //end if
// @codeCoverageIgnoreStart
return parent::render($request, $e);
// @codeCoverageIgnoreEnd
}
/**
* Generate a json response for any api error case
*
* @param \Illuminate\Http\Request $request
* @param \Throwable $e
* @return \Illuminate\Http\JsonResponse
*/
private function handleApiException(Request $request, \Throwable $e): JsonResponse
{
switch (get_class($e)) {
case AuthenticationException::class:
/** @var AuthenticationException $e */
return $this->getReponse(
$request,
401,
ApiError::apiAuthFailed()->value,
sprintf('%s, %s', ApiError::apiAuthFailed()->label, $e->getMessage())
);
case MethodNotAllowedHttpException::class:
/** @var MethodNotAllowedHttpException $e */
return $this->getReponse(
$request,
$e->getStatusCode(),
ApiError::methodNotAllowed()->value,
sprintf('%s, %s', ApiError::methodNotAllowed()->label, $e->getMessage())
);
case ValidationException::class:
/** @var ValidationException $e */
return $this->getReponse(
$request,
$e->status,
ApiError::validationFailed()->value,
sprintf(ApiError::validationFailed()->label, $e->getMessage()),
['errors' => $e->errors()]
);
case ModelNotFoundException::class:
/** @var ModelNotFoundException $e */
return $this->getReponse(
$request,
404,
ApiError::modelNotFound()->value,
sprintf(
ApiError::modelNotFound()->label,
\array_slice(explode('\\', (string)$e->getModel()), -1)[0]
)
);
case ApiErrorException::class:
/** @var ApiErrorException $e */
return $this->getReponse(
$request,
$e->getStatusCode(),
$e->getCode(),
$e->getMessage()
);
case ThrottleRequestsException::class:
/** @var ThrottleRequestsException $e */
return $this->getReponse(
$request,
429,
ApiError::throttleRequestsException()->value,
ApiError::throttleRequestsException()->label
);
case AuthorizationException::class:
/** @var AuthorizationException $e */
return $this->getReponse(
$request,
403,
ApiError::authorizationException()->value,
ApiError::authorizationException()->label
);
} //end switch
// @codeCoverageIgnoreStart
if (config('app.env') === 'testing') {
// phpcs:ignore Squiz.PHP.DiscouragedFunctions.Found
print_r((string)$e);
}
return $this->getReponse($request, 500, intval($e->getCode()), $e->getMessage());
// @codeCoverageIgnoreEnd
}
/**
* Generate an Api json response
*
* @param \Illuminate\Http\Request $request
* @param integer $httpCode
* @param integer $apiCode
* @param string $message
* @param array $data
* @return \Illuminate\Http\JsonResponse
*/
private static function getReponse(
Request $request,
int $httpCode,
int $apiCode,
string $message,
array $data = []
): JsonResponse {
return (new ApiResponseResource(
(object)array_merge($data, ['message' => $message, 'code' => $apiCode]),
ApiStatus::KO()
))->toResponse($request)->setStatusCode($httpCode);
}
}