<commit_before><?php

namespace Helldar\ApiResponse\Support;

use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Foundation\Http\Exceptions\MaintenanceModeException;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Routing\Router;
use Illuminate\Support\Arr;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Throwable;

abstract class LaravelException extends ExceptionHandler
{
    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Throwable  $e
     *
     * @throws \Throwable
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function render($request, Throwable $e)
    {
        if ($this->isJson($request) && $e instanceof MaintenanceModeException) {
            return api_response($e, 503);
        }

        if (method_exists($e, 'render') && $response = $e->render($request)) {
            return Router::toResponse($request, $response);
        } elseif ($e instanceof Responsable) {
            return $e->toResponse($request);
        }

        $e = $this->prepareException($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 $this->isJson($request)
            ? $this->prepareJsonResponse($request, $e)
            : $this->prepareResponse($request, $e);
    }

    protected function invalidJson($request, ValidationException $exception)
    {
        return api_response($exception);
    }

    protected function unauthenticated($request, AuthenticationException $exception)
    {
        return $this->isJson($request)
            ? api_response($exception, 401)
            : redirect()->guest(route('login'));
    }

    /**
     * @param  \Illuminate\Http\Request  $request
     * @param  Symfony\Component\HttpFoundation\JsonResponse|Throwable  $response
     *
     * @return bool
     */
    protected function isJson($request, $response = null): bool
    {
        return $request->expectsJson() || $request->isJson() || $request->is('api*') || $response instanceof JsonResponse;
    }

    protected function prepareJsonResponse($request, Throwable $e)
    {
        return api_response(
            $this->getExceptionMessage($e),
            $this->isHttpException($e) ? $e->getStatusCode() : 500,
            $this->getExceptionTrace($e),
            $this->isHttpException($e) ? $e->getHeaders() : [],
            true,
            get_class($e)
        );
    }

    protected function getExceptionMessage(Throwable $e)
    {
        $converted = parent::convertExceptionToArray($e);

        return Arr::get($converted, 'message');
    }

    protected function getExceptionTrace(Throwable $e)
    {
        $converted = parent::convertExceptionToArray($e);

        return config('app.debug')
            ? ['info' => Arr::except($converted, 'message')]
            : [];
    }
}<commit_msg>Added the ability to attach additional data when sending errors<commit_after><?php

namespace Helldar\ApiResponse\Support;

use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Foundation\Http\Exceptions\MaintenanceModeException;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Routing\Router;
use Illuminate\Support\Arr;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Throwable;

abstract class LaravelException extends ExceptionHandler
{
    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Throwable  $e
     *
     * @throws \Throwable
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function render($request, Throwable $e)
    {
        if ($this->isJson($request) && $e instanceof MaintenanceModeException) {
            return $this->response($e, 503);
        }

        if (method_exists($e, 'render') && $response = $e->render($request)) {
            return Router::toResponse($request, $response);
        } elseif ($e instanceof Responsable) {
            return $e->toResponse($request);
        }

        $e = $this->prepareException($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 $this->isJson($request)
            ? $this->prepareJsonResponse($request, $e)
            : $this->prepareResponse($request, $e);
    }

    protected function invalidJson($request, ValidationException $exception)
    {
        return $this->response($exception);
    }

    protected function unauthenticated($request, AuthenticationException $exception)
    {
        return $this->isJson($request)
            ? $this->response($exception, 401)
            : redirect()->guest(route('login'));
    }

    /**
     * @param  \Illuminate\Http\Request  $request
     * @param  Symfony\Component\HttpFoundation\JsonResponse|Throwable  $response
     *
     * @return bool
     */
    protected function isJson($request, $response = null): bool
    {
        return $request->expectsJson() || $request->isJson() || $request->is('api*') || $response instanceof JsonResponse;
    }

    protected function prepareJsonResponse($request, Throwable $e)
    {
        return api_response(
            $this->getExceptionMessage($e),
            $this->isHttpException($e) ? $e->getStatusCode() : 500,
            array_merge($this->with(), $this->getExceptionTrace($e)),
            $this->isHttpException($e) ? $e->getHeaders() : [],
            true,
            get_class($e)
        );
    }

    protected function getExceptionMessage(Throwable $e)
    {
        $converted = parent::convertExceptionToArray($e);

        return Arr::get($converted, 'message');
    }

    protected function getExceptionTrace(Throwable $e)
    {
        $converted = parent::convertExceptionToArray($e);

        return config('app.debug')
            ? ['info' => Arr::except($converted, 'message')]
            : [];
    }

    protected function with(): array
    {
        return [];
    }

    protected function response($data, int $status_code = 200): JsonResponse
    {
        return api_response($data, $status_code, $this->with());
    }
}
{'fraction_non_alphanumeric': 0.1277991727285694, 'fraction_numerical': 0.002995293110825845, 'mean_word_length': 2.844298245614035, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 52, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4801796', 'n_tokens_mistral': 1894, 'n_tokens_neox': 1891, 'n_words': 378}