ExceptionError   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 4
dl 0
loc 98
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
B run() 0 35 7
B treatTraceData() 0 29 8
A arrayFilterRecursive() 0 15 4
1
<?php
2
3
namespace Igorsgm\LaravelApiResponses\Macros;
4
5
use Igorsgm\LaravelApiResponses\ResponseMacroInterface;
6
use Illuminate\Http\JsonResponse;
7
use Illuminate\Routing\ResponseFactory;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\Str;
10
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
11
use Throwable;
12
13
class ExceptionError implements ResponseMacroInterface
14
{
15
    /**
16
     * @param  ResponseFactory  $factory
17
     */
18
    public function run($factory)
19
    {
20
        $factory->macro('exceptionError',
21
            /**
22
             * Return a new error JSON response from the application coming from an exception.
23
             * Called like: response()->exceptionError(...)
24
             *
25
             * @param  Throwable  $e
26
             * @param  string  $message
27
             * @param  int  $status
28
             * @param  array  $headers
29
             * @return JsonResponse
30
             */
31
            function ($e, $message = '', $status = 0, array $headers = []) use ($factory) {
32
                $errors = method_exists($e, 'errors') ? $e->errors() : [];
33
34
                if (empty($message)) {
35
                    $showExceptionMessage = config('app.debug') || $e instanceof HttpExceptionInterface;
36
                    $message = $showExceptionMessage ? $e->getMessage() : 'Server Error';
37
                }
38
39
                $status = !empty($status) ? (int) $status : $e->getCode();
40
41
                $debugData = [];
42
                if (config('app.debug')) {
43
                    $debugData = [
44
                        'file' => $e->getFile(),
45
                        'line' => $e->getLine(),
46
                        'trace' => ExceptionError::treatTraceData($e),
47
                    ];
48
                }
49
50
                return $factory->error($errors, $message, $status, $headers, $debugData);
51
            });
52
    }
53
54
    /**
55
     * Filtering exception's trace to show the data that matters more
56
     * @param  Throwable  $e
57
     * @return array
58
     */
59
    public static function treatTraceData($e)
60
    {
61
        $traceAsString = explode("\n", $e->getTraceAsString());
62
        $trace = collect($e->getTrace());
63
64
        if (!config('laravel-api-responses.treat_exception_trace')) {
65
            return $trace->map(function ($trace) {
66
                return Arr::except($trace, ['args']);
67
            })->all();
68
        }
69
70
        return $trace->transform(function ($trace, $key) use ($traceAsString) {
71
            if ($key == 0 || !isset($trace['file']) || Str::contains($traceAsString[$key], 'App\\') ||
72
                !Str::contains($trace['file'], ['vendor/', '/public/index.php', ' phar://', "#1 "])
73
            ) {
74
                unset($trace['type']);
75
                if (isset($trace['args'])) {
76
                    $trace['args'] = json_decode(json_encode($trace['args']), true);
77
                    $trace['args'] = self::arrayFilterRecursive($trace['args']);
78
79
                    if (empty($trace['args'])) {
80
                        unset($trace['args']);
81
                    }
82
                }
83
84
                return $trace;
85
            }
86
        })->filter()->toArray();
87
    }
88
89
    /**
90
     * Removes empty elements of an array recursively
91
     *
92
     * @param  array  $array
93
     * @return array
94
     */
95
    public static function arrayFilterRecursive($array): array
96
    {
97
        if (!is_array($array)) {
98
            return [];
99
        }
100
101
        foreach ($array as &$value) {
102
            if (is_array($value)) {
103
                $value = self::arrayFilterRecursive($value);
104
            }
105
        }
106
        return array_filter($array, function ($var) {
107
            return !empty($var);
108
        });
109
    }
110
}
111