webworld888/app/Exceptions/Handler.php
2021-10-26 19:14:12 +09:00

357 lines
10 KiB
PHP

<?php
/**
* Handler.php
*
* PHP version 7
*
* @category Exceptions
* @package App\Exceptions
* @license https://opensource.org/licenses/MIT MIT
* @link https://laravel.com
*/
namespace App\Exceptions;
use Exception;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Event;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Routing\Router;
use Illuminate\Validation\ValidationException;
use XePresenter;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Session\TokenMismatchException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Xpressengine\Plugin\Exceptions\PluginFileNotFoundException;
use Xpressengine\Support\Exceptions\AccessDeniedHttpException;
use Xpressengine\Support\Exceptions\HttpXpressengineException;
/**
* Class Handler
*
* @category Exceptions
* @package App\Exceptions
* @license https://opensource.org/licenses/MIT MIT
* @link https://laravel.com
*/
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var array
*/
protected $dontReport = [
HttpException::class,
HttpXpressengineException::class,
ModelNotFoundException::class,
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
{
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Symfony\Component\HttpFoundation\Response
*/
public function render($request, Exception $e)
{
if (method_exists($e, 'render') && $response = $e->render($request)) {
return Router::toResponse($request, $response);
} elseif ($e instanceof Responsable) {
return $e->toResponse($request);
}
Event::fire('exception.handler:prepare.before', [$e]);
$e = $this->prepareException($e);
Event::fire('exception.handler:prepare.after', [$e]);
if ($e instanceof HttpResponseException) {
return $e->getResponse();
} elseif ($e instanceof AuthenticationException) {
return $this->unauthenticated($request, $e);
} elseif ($e instanceof ValidationException) {
return $this->convertValidationExceptionToResponse($e, $request);
}
return $request->expectsJson()
? $this->prepareJsonResponse($request, $e)
: $this->prepareResponse($request, $e);
}
/**
* Prepare exception for rendering.
*
* @param \Exception $e
* @return \Exception
*/
protected function prepareException(Exception $e)
{
if ($e instanceof ModelNotFoundException) {
$e = new NotFoundHttpException('xe::pageNotFound', $e);
// $e = new NotFoundHttpException($e->getMessage(), $e);
} elseif ($e instanceof NotFoundHttpException) {
$e = new NotFoundHttpException('xe::pageNotFound', $e);
} elseif ($e instanceof AuthorizationException) {
$e = new AccessDeniedHttpException();
} elseif ($e instanceof TokenMismatchException) {
$e = new HttpException(419, 'xe::tokenMismatch');
}
return $this->convert($e);
}
/**
* exception filter for send xpressengine message
*
* @param Exception $e
* @return HttpXpressengineException|Exception
*/
protected function convert(Exception $e)
{
$converted = $e;
if ($e instanceof HttpXpressengineException) {
$e->setMessage(xe_trans($e->getMessage(), $e->getArgs()));
$converted = $e;
} elseif ($e instanceof HttpException) {
/** @var HttpException $e */
$converted = new HttpXpressengineException([], $e->getStatusCode(), $e);
$message = xe_trans($e->getMessage());
if ('' === $message) {
$message = get_class($e);
}
$converted->setMessage($message);
} elseif ($e->getPrevious() && $this->isHttpException($e->getPrevious())) {
$converted = $this->convert($e->getPrevious());
}
return $converted;
}
/**
* Determine if the given exception is an HTTP exception.
*
* @param \Exception $e
* @return bool
*/
protected function isHttpException(Exception $e)
{
return $e instanceof HttpException || $this->isHttpXpressengineException($e);
}
/**
* Determine if the given exception is an HTTP exception.
*
* @param \Exception $e
* @return bool
*/
protected function isHttpXpressengineException(Exception $e = null)
{
return $e !== null && $e instanceof HttpXpressengineException;
}
/**
* is fatal error
*
* @param Exception $e
* @return bool
*/
protected function isFatalError(Exception $e)
{
return $e instanceof \Symfony\Component\Debug\Exception\FatalErrorException;
}
/**
* Prepare a response for the given exception.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function prepareResponse($request, Exception $e)
{
if (!$this->isHttpException($e) && config('app.debug')) {
return $this->toIlluminateResponse(
$this->convertExceptionToResponse($e), $e
);
}
if (!$this->isHttpException($e)) {
$e = new HttpXpressengineException([], 500, $e);
$e->setMessage(xe_trans('xe::systemError'));
}
return (new \Illuminate\Pipeline\Pipeline($this->container))
->send($request)
->through(!session()->isStarted() ? [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Session\Middleware\StartSession::class,
] : [])
->then(function ($request) use ($e) {
return $this->toIlluminateResponse(
$this->isFatalError($e) || !$this->withTheme() ?
$this->renderWithoutXE($e) :
$this->renderWithTheme($e, $request),
$e
);
});
}
/**
* Render the given HttpXpressengineException.
*
* @param HttpXpressengineException $e
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function renderWithoutXE(HttpXpressengineException $e)
{
$status = $e->getStatusCode();
$path = $this->getPath();
if (view()->exists("{$path}.{$status}") === false) {
$status = 500;
}
return $this->getView($path, $status, $e);
}
/**
* Render the given HttpXpressengineException.
*
* @param HttpXpressengineException $e
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function renderWithTheme(HttpXpressengineException $e, Request $request)
{
$status = $e->getStatusCode();
// return for api
if ($request->expectsJson()) {
$view = XePresenter::makeApi([
'message' => $e->getMessage(),
]);
return response($view, $status);
}
$path = $this->getPath();
if (view()->exists("{$path}.{$status}") === false) {
$status = 500;
}
try {
if ($status == 503) {
// maintenance mode
$view = $this->getView($path, $status, $e);
} else {
$view = $this->getTheme($path, $status, $e);
}
} catch (Exception $renderError) {
$view = $this->getView($path, $status, $e);
}
return $view;
}
/**
* render with xe theme(use Presenter)
*
* @param $path
* @param $status
* @param HttpXpressengineException $e
* @return Response
*/
protected function getTheme($path, $status, HttpXpressengineException $e)
{
XePresenter::setSkinTargetId(null);
$view = XePresenter::make("{$path}.{$status}", [
'exception' => $e,
'path' => $path,
'xe' => true,
]);
return response($view);
}
/**
* render without xe
*
* @param $path
* @param $status
* @param Exception $e
* @return Response
*/
protected function getView($path, $status, HttpXpressengineException $e)
{
$view = response()->view("{$path}.{$status}", [
'exception' => $e,
'path' => $path,
'xe' => false,
], $status, $e->getHeaders());
return $view;
}
/**
* Convert the given exception to an array.
*
* @param \Exception $e
* @return array
*/
protected function convertExceptionToArray(Exception $e)
{
$arr = parent::convertExceptionToArray($e);
if ($arr['message'] === 'Server Error') {
$arr['message'] = xe_trans('xe::systemError');
}
return $arr;
}
/**
* Get view path for errors
*
* @return string
*/
protected function getPath()
{
return config('view.error.path');
}
/**
* Determine if use theme with error view
*
* @return bool
*/
protected function withTheme()
{
return config('view.error.theme', true);
}
}