%PDF- %PDF-
Direktori : /home/silvzytp/calling_code/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/ |
Current File : //home/silvzytp/calling_code/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php |
<?php namespace Illuminate\Foundation\Exceptions; use Closure; use Exception; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Auth\AuthenticationException; use Illuminate\Console\View\Components\BulletList; use Illuminate\Console\View\Components\Error; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandlerContract; use Illuminate\Contracts\Foundation\ExceptionRenderer; use Illuminate\Contracts\Support\Responsable; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\MultipleRecordsFoundException; use Illuminate\Database\RecordsNotFoundException; use Illuminate\Http\Exceptions\HttpResponseException; use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Response; use Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException; use Illuminate\Routing\Router; use Illuminate\Session\TokenMismatchException; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Reflector; use Illuminate\Support\Traits\ReflectsClosures; use Illuminate\Support\ViewErrorBag; use Illuminate\Validation\ValidationException; use InvalidArgumentException; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Symfony\Component\Console\Application as ConsoleApplication; use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; use Symfony\Component\HttpFoundation\RedirectResponse as SymfonyRedirectResponse; use Symfony\Component\HttpFoundation\Response as SymfonyResponse; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Throwable; class Handler implements ExceptionHandlerContract { use ReflectsClosures; /** * The container implementation. * * @var \Illuminate\Contracts\Container\Container */ protected $container; /** * A list of the exception types that are not reported. * * @var array<int, class-string<\Throwable>> */ protected $dontReport = []; /** * The callbacks that should be used during reporting. * * @var \Illuminate\Foundation\Exceptions\ReportableHandler[] */ protected $reportCallbacks = []; /** * A map of exceptions with their corresponding custom log levels. * * @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*> */ protected $levels = []; /** * The callbacks that should be used during rendering. * * @var \Closure[] */ protected $renderCallbacks = []; /** * The registered exception mappings. * * @var array<string, \Closure> */ protected $exceptionMap = []; /** * A list of the internal exception types that should not be reported. * * @var array<int, class-string<\Throwable>> */ protected $internalDontReport = [ AuthenticationException::class, AuthorizationException::class, BackedEnumCaseNotFoundException::class, HttpException::class, HttpResponseException::class, ModelNotFoundException::class, MultipleRecordsFoundException::class, RecordsNotFoundException::class, SuspiciousOperationException::class, TokenMismatchException::class, ValidationException::class, ]; /** * A list of the inputs that are never flashed for validation exceptions. * * @var array<int, string> */ protected $dontFlash = [ 'current_password', 'password', 'password_confirmation', ]; /** * Create a new exception handler instance. * * @param \Illuminate\Contracts\Container\Container $container * @return void */ public function __construct(Container $container) { $this->container = $container; $this->register(); } /** * Register the exception handling callbacks for the application. * * @return void */ public function register() { // } /** * Register a reportable callback. * * @param callable $reportUsing * @return \Illuminate\Foundation\Exceptions\ReportableHandler */ public function reportable(callable $reportUsing) { if (! $reportUsing instanceof Closure) { $reportUsing = Closure::fromCallable($reportUsing); } return tap(new ReportableHandler($reportUsing), function ($callback) { $this->reportCallbacks[] = $callback; }); } /** * Register a renderable callback. * * @param callable $renderUsing * @return $this */ public function renderable(callable $renderUsing) { if (! $renderUsing instanceof Closure) { $renderUsing = Closure::fromCallable($renderUsing); } $this->renderCallbacks[] = $renderUsing; return $this; } /** * Register a new exception mapping. * * @param \Closure|string $from * @param \Closure|string|null $to * @return $this * * @throws \InvalidArgumentException */ public function map($from, $to = null) { if (is_string($to)) { $to = fn ($exception) => new $to('', 0, $exception); } if (is_callable($from) && is_null($to)) { $from = $this->firstClosureParameterType($to = $from); } if (! is_string($from) || ! $to instanceof Closure) { throw new InvalidArgumentException('Invalid exception mapping.'); } $this->exceptionMap[$from] = $to; return $this; } /** * Indicate that the given exception type should not be reported. * * @param string $class * @return $this */ public function ignore(string $class) { $this->dontReport[] = $class; return $this; } /** * Set the log level for the given exception type. * * @param class-string<\Throwable> $type * @param \Psr\Log\LogLevel::* $level * @return $this */ public function level($type, $level) { $this->levels[$type] = $level; return $this; } /** * Report or log an exception. * * @param \Throwable $e * @return void * * @throws \Throwable */ public function report(Throwable $e) { $e = $this->mapException($e); if ($this->shouldntReport($e)) { return; } if (Reflector::isCallable($reportCallable = [$e, 'report']) && $this->container->call($reportCallable) !== false) { return; } foreach ($this->reportCallbacks as $reportCallback) { if ($reportCallback->handles($e) && $reportCallback($e) === false) { return; } } try { $logger = $this->container->make(LoggerInterface::class); } catch (Exception $ex) { throw $e; } $level = Arr::first( $this->levels, fn ($level, $type) => $e instanceof $type, LogLevel::ERROR ); $context = $this->buildExceptionContext($e); method_exists($logger, $level) ? $logger->{$level}($e->getMessage(), $context) : $logger->log($level, $e->getMessage(), $context); } /** * Determine if the exception should be reported. * * @param \Throwable $e * @return bool */ public function shouldReport(Throwable $e) { return ! $this->shouldntReport($e); } /** * Determine if the exception is in the "do not report" list. * * @param \Throwable $e * @return bool */ protected function shouldntReport(Throwable $e) { $dontReport = array_merge($this->dontReport, $this->internalDontReport); return ! is_null(Arr::first($dontReport, fn ($type) => $e instanceof $type)); } /** * Create the context array for logging the given exception. * * @param \Throwable $e * @return array */ protected function buildExceptionContext(Throwable $e) { return array_merge( $this->exceptionContext($e), $this->context(), ['exception' => $e] ); } /** * Get the default exception context variables for logging. * * @param \Throwable $e * @return array */ protected function exceptionContext(Throwable $e) { if (method_exists($e, 'context')) { return $e->context(); } return []; } /** * Get the default context variables for logging. * * @return array */ protected function context() { try { return array_filter([ 'userId' => Auth::id(), ]); } catch (Throwable $e) { return []; } } /** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return \Symfony\Component\HttpFoundation\Response * * @throws \Throwable */ public function render($request, Throwable $e) { if (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); } if ($e instanceof Responsable) { return $e->toResponse($request); } $e = $this->prepareException($this->mapException($e)); if ($response = $this->renderViaCallbacks($request, $e)) { return $response; } return match (true) { $e instanceof HttpResponseException => $e->getResponse(), $e instanceof AuthenticationException => $this->unauthenticated($request, $e), $e instanceof ValidationException => $this->convertValidationExceptionToResponse($e, $request), default => $this->renderExceptionResponse($request, $e), }; } /** * Prepare exception for rendering. * * @param \Throwable $e * @return \Throwable */ protected function prepareException(Throwable $e) { return match (true) { $e instanceof BackedEnumCaseNotFoundException => new NotFoundHttpException($e->getMessage(), $e), $e instanceof ModelNotFoundException => new NotFoundHttpException($e->getMessage(), $e), $e instanceof AuthorizationException && $e->hasStatus() => new HttpException( $e->status(), $e->response()?->message() ?: (Response::$statusTexts[$e->status()] ?? 'Whoops, looks like something went wrong.'), $e ), $e instanceof AuthorizationException && ! $e->hasStatus() => new AccessDeniedHttpException($e->getMessage(), $e), $e instanceof TokenMismatchException => new HttpException(419, $e->getMessage(), $e), $e instanceof SuspiciousOperationException => new NotFoundHttpException('Bad hostname provided.', $e), $e instanceof RecordsNotFoundException => new NotFoundHttpException('Not found.', $e), default => $e, }; } /** * Map the exception using a registered mapper if possible. * * @param \Throwable $e * @return \Throwable */ protected function mapException(Throwable $e) { if (method_exists($e, 'getInnerException') && ($inner = $e->getInnerException()) instanceof Throwable) { return $inner; } foreach ($this->exceptionMap as $class => $mapper) { if (is_a($e, $class)) { return $mapper($e); } } return $e; } /** * Try to render a response from request and exception via render callbacks. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return mixed * * @throws \ReflectionException */ protected function renderViaCallbacks($request, Throwable $e) { foreach ($this->renderCallbacks as $renderCallback) { foreach ($this->firstClosureParameterTypes($renderCallback) as $type) { if (is_a($e, $type)) { $response = $renderCallback($e, $request); if (! is_null($response)) { return $response; } } } } } /** * Render a default exception response if any. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return \Symfony\Component\HttpFoundation\Response */ protected function renderExceptionResponse($request, Throwable $e) { return $this->shouldReturnJson($request, $e) ? $this->prepareJsonResponse($request, $e) : $this->prepareResponse($request, $e); } /** * Convert an authentication exception into a response. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Auth\AuthenticationException $exception * @return \Symfony\Component\HttpFoundation\Response */ protected function unauthenticated($request, AuthenticationException $exception) { return $this->shouldReturnJson($request, $exception) ? response()->json(['message' => $exception->getMessage()], 401) : redirect()->guest($exception->redirectTo() ?? route('login')); } /** * Create a response object from the given validation exception. * * @param \Illuminate\Validation\ValidationException $e * @param \Illuminate\Http\Request $request * @return \Symfony\Component\HttpFoundation\Response */ protected function convertValidationExceptionToResponse(ValidationException $e, $request) { if ($e->response) { return $e->response; } return $this->shouldReturnJson($request, $e) ? $this->invalidJson($request, $e) : $this->invalid($request, $e); } /** * Convert a validation exception into a response. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Validation\ValidationException $exception * @return \Illuminate\Http\Response */ protected function invalid($request, ValidationException $exception) { return redirect($exception->redirectTo ?? url()->previous()) ->withInput(Arr::except($request->input(), $this->dontFlash)) ->withErrors($exception->errors(), $request->input('_error_bag', $exception->errorBag)); } /** * Convert a validation exception into a JSON response. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Validation\ValidationException $exception * @return \Illuminate\Http\JsonResponse */ protected function invalidJson($request, ValidationException $exception) { return response()->json([ 'message' => $exception->getMessage(), 'errors' => $exception->errors(), ], $exception->status); } /** * Determine if the exception handler response should be JSON. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return bool */ protected function shouldReturnJson($request, Throwable $e) { return $request->expectsJson(); } /** * Prepare a response for the given exception. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return \Symfony\Component\HttpFoundation\Response */ protected function prepareResponse($request, Throwable $e) { if (! $this->isHttpException($e) && config('app.debug')) { return $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e)->prepare($request); } if (! $this->isHttpException($e)) { $e = new HttpException(500, $e->getMessage(), $e); } return $this->toIlluminateResponse( $this->renderHttpException($e), $e )->prepare($request); } /** * Create a Symfony response for the given exception. * * @param \Throwable $e * @return \Symfony\Component\HttpFoundation\Response */ protected function convertExceptionToResponse(Throwable $e) { return new SymfonyResponse( $this->renderExceptionContent($e), $this->isHttpException($e) ? $e->getStatusCode() : 500, $this->isHttpException($e) ? $e->getHeaders() : [] ); } /** * Get the response content for the given exception. * * @param \Throwable $e * @return string */ protected function renderExceptionContent(Throwable $e) { try { return config('app.debug') && app()->has(ExceptionRenderer::class) ? $this->renderExceptionWithCustomRenderer($e) : $this->renderExceptionWithSymfony($e, config('app.debug')); } catch (Throwable $e) { return $this->renderExceptionWithSymfony($e, config('app.debug')); } } /** * Render an exception to a string using the registered `ExceptionRenderer`. * * @param \Throwable $e * @return string */ protected function renderExceptionWithCustomRenderer(Throwable $e) { return app(ExceptionRenderer::class)->render($e); } /** * Render an exception to a string using Symfony. * * @param \Throwable $e * @param bool $debug * @return string */ protected function renderExceptionWithSymfony(Throwable $e, $debug) { $renderer = new HtmlErrorRenderer($debug); return $renderer->render($e)->getAsString(); } /** * Render the given HttpException. * * @param \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface $e * @return \Symfony\Component\HttpFoundation\Response */ protected function renderHttpException(HttpExceptionInterface $e) { $this->registerErrorViewPaths(); if ($view = $this->getHttpExceptionView($e)) { return response()->view($view, [ 'errors' => new ViewErrorBag, 'exception' => $e, ], $e->getStatusCode(), $e->getHeaders()); } return $this->convertExceptionToResponse($e); } /** * Register the error template hint paths. * * @return void */ protected function registerErrorViewPaths() { (new RegisterErrorViewPaths)(); } /** * Get the view used to render HTTP exceptions. * * @param \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface $e * @return string|null */ protected function getHttpExceptionView(HttpExceptionInterface $e) { $view = 'errors::'.$e->getStatusCode(); if (view()->exists($view)) { return $view; } $view = substr($view, 0, -2).'xx'; if (view()->exists($view)) { return $view; } return null; } /** * Map the given exception into an Illuminate response. * * @param \Symfony\Component\HttpFoundation\Response $response * @param \Throwable $e * @return \Illuminate\Http\Response */ protected function toIlluminateResponse($response, Throwable $e) { if ($response instanceof SymfonyRedirectResponse) { $response = new RedirectResponse( $response->getTargetUrl(), $response->getStatusCode(), $response->headers->all() ); } else { $response = new Response( $response->getContent(), $response->getStatusCode(), $response->headers->all() ); } return $response->withException($e); } /** * Prepare a JSON response for the given exception. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return \Illuminate\Http\JsonResponse */ protected function prepareJsonResponse($request, Throwable $e) { return new JsonResponse( $this->convertExceptionToArray($e), $this->isHttpException($e) ? $e->getStatusCode() : 500, $this->isHttpException($e) ? $e->getHeaders() : [], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); } /** * Convert the given exception to an array. * * @param \Throwable $e * @return array */ protected function convertExceptionToArray(Throwable $e) { return config('app.debug') ? [ 'message' => $e->getMessage(), 'exception' => get_class($e), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => collect($e->getTrace())->map(fn ($trace) => Arr::except($trace, ['args']))->all(), ] : [ 'message' => $this->isHttpException($e) ? $e->getMessage() : 'Server Error', ]; } /** * Render an exception to the console. * * @param \Symfony\Component\Console\Output\OutputInterface $output * @param \Throwable $e * @return void * * @internal This method is not meant to be used or overwritten outside the framework. */ public function renderForConsole($output, Throwable $e) { if ($e instanceof CommandNotFoundException) { $message = str($e->getMessage())->explode('.')->first(); if (! empty($alternatives = $e->getAlternatives())) { $message .= '. Did you mean one of these?'; with(new Error($output))->render($message); with(new BulletList($output))->render($e->getAlternatives()); $output->writeln(''); } else { with(new Error($output))->render($message); } return; } (new ConsoleApplication)->renderThrowable($e, $output); } /** * Determine if the given exception is an HTTP exception. * * @param \Throwable $e * @return bool */ protected function isHttpException(Throwable $e) { return $e instanceof HttpExceptionInterface; } }